三步教你编写一个Neumorphism风格的小时钟

举报
空城机 发表于 2021/08/20 09:25:27 2021/08/20
【摘要】 自己动手丰衣足食,Neumorphism新拟物风格看起来真的舒服,自己动手做一个小组件进行练习吧

又到了自己编写组件的时节了
在这里插入图片描述

作为一名前端开发者,平时也是阔以没事可以写写自定义的组件,增加一下自己的阅历,实际开发中用到也可以通过CV大法去快速开发


先提前来看一下最终的效果:
在这里插入图片描述


先问一个小问题,现在大家现在更习惯于看哪种样式的时间,是钟表类型还是数字类型?(虽然你们的回答影响不了我做一个钟表啦

钟表时间:

在这里插入图片描述

数字时间:

在这里插入图片描述


Neumorphism

目前网上的一些时钟风格不太喜欢,之前偶然看到一款新拟物风格Neumorphism的设计,让我眼前不禁一亮
所以本次时钟组件的风格就决定是你啦—新拟物

在这里插入图片描述

Neumorphism风格页面

在这里插入图片描述



正文开始

上面又水了一堆话,增加了一下文字的数量,真是太开森了

下面正式开始组件的制作流程

一、时钟表盘编写

因为本人使用的是vue,所以编写的也是.vue组件

先搭建一个clock.vue的组件,设定好props可能会接收的宽高,还有阴影颜色。
阴影部分使用box-shadow进行设置

其中像Compute中的styleVar内容类似于CSS 中的:root
也可以去此文章中查看相关方法:自己动手丰衣足食系列の自定义下拉框 vue 组件

在主页面app.vue中设置全局颜色为#EBE6DA

在CSS 样式编写中,计算位置等值可以使用calc加var的方式计算

代码:

<template>
    <!-- 时钟 -->
    <div class="clock" :style="styleVar">
        <!-- 内圈 -->
        <div class="innerBorder">
            <!-- 时钟刻度 -->
            <div class="scale mark1"></div>
            <div class="scale mark2"></div>
            <div class="scale mark3"></div>
            <div class="scale mark4"></div>
            <div class="scale mark5"></div>
            <div class="scale mark6"></div>
            <div class="scale mark7"></div>
            <div class="scale mark8"></div>
        </div>
        <!-- 内圈波浪 -->
        <div class="wave"></div>
    </div>
</template>
<script>
export default {
    name: 'clock',
    components: {},
    props: {
        bgsize: {
            type: Number,
            default: 180
        },
        bgcolor: {
            type: String,
            default: '#D1CCC0'
        }
    },
    data() {
        return {
        };
    },
    created() {},
    mounted() {},
    watch: {},
    computed: {
        styleVar() {
            return {
                '--clock-size': this.bgsize + 'px',
                '--clock-bgcolor': this.bgcolor,
                '--length-log2E': ((this.bgsize - 10) / 2) / Math.LOG2E + 'px',
            }
        }
    },
    methods: {
        
    },
};
</script>
<style scoped>
    /* 外部大小和阴影 */
    .clock {
        width: var(--clock-size);
        height: var(--clock-size);
        border-radius: 50%;
        box-shadow: 5px 5px 10px var(--clock-bgcolor), -4px -4px 8px #fff;
    }
    /* 内阴影 */
    .innerBorder {
        /* calc加var计算 */
        width: calc(var(--clock-size) - 10px);
        height: calc(var(--clock-size) - 10px);
        position: relative;
        left: 5px;
        top: 5px;
        box-shadow: -3px -3px 6px #fff inset, 3px 3px 6px var(--clock-bgcolor) inset;
        border-radius: 50%;
    }
    /* 时钟刻度 */
    .scale {
        width: 2px;
        height: 8px;
        position: absolute;
        box-shadow: 1px 1px 1px #9D958F inset, -1px -1px 1px var(--clock-bgcolor) inset;
        border-radius: 1px;
    }
    /* 设置小刻度位置 */
    .mark1 {
        left: calc(50% - 1px);
        top: 2px;
    }
    .mark2 {
        transform: rotate(45deg);
        left: calc(50% + var(--length-log2E) );
        top: calc(50% - var(--length-log2E) );
    }
    .mark3 {
        transform: rotate(90deg);
        left: calc(100% - 7px);
        top: calc(50% - 1px);
    }
    .mark4 {
        transform: rotate(135deg);
        left: calc(50% + var(--length-log2E) - 5px);
        top: calc(50% + var(--length-log2E) - 5px);
    }
    .mark5 {
        left: calc(50% - 1px);
        bottom: 2px;
    }
    .mark6 {
        transform: rotate(45deg);
        left: calc(50% - var(--length-log2E) + 5px);
        top: calc(50% + var(--length-log2E) - 5px);
    }
    .mark7 {
        transform: rotate(90deg);
        left: 2px;
        top: calc(50% - 1px);
    }
    .mark8 {
        transform: rotate(135deg);
        left: calc(50% - var(--length-log2E) );
        top: calc(50% - var(--length-log2E) );
    }
    /* 中间波浪 */
    .wave {
        width: 30%;
        height: 30%;
        position: absolute;
        left: 35%;
        top: 35%;
        box-shadow: 3px 3px 9px var(--clock-bgcolor), -3px -3px 9px #fff;
        border-radius: 50%;
        filter: blur(1px);
        animation: wavemove 4s infinite linear;
    }
    @keyframes wavemove {
        0% {
            transform: scale(0.5);
        }
        50% {
            transform: scale(1);
            opacity: 1;
        }
        100% {
            transform: scale(1.7);
            opacity: 0;
        }
    }
</style>

效果:
在这里插入图片描述


二、时钟指针编写

在编写指针时需要注意,指针的旋转运动是围绕圆心进行的,使用transform来改变旋转

所以需要使用transform-origin: bottom来设置选择的基准点,之后旋转rotate改变

在这里插入图片描述

在样式编写完成之后,就可以将当前的北京时间与指针、分针、秒针的转动相结合起来了

这里的原理其实更加简单,使用new Date()获取到当前的时分秒,然后再将时分秒按比例转换成度数deg

// 校准时钟指针方法
currentTime:function(){
    let date = new Date();
    this.hour = date.getHours();
    this.minute = date.getMinutes();
    this.second = date.getSeconds();
    document.getElementsByClassName('hourhand')[0].style.transform = 'rotate(' + this.hour / 24 * 360 + 'deg)';
    document.getElementsByClassName('minhand')[0].style.transform = 'rotate(' + this.minute / 60 * 360 + 'deg)';
    document.getElementsByClassName('sechand')[0].style.transform = 'rotate(' + this.second / 60 * 360 + 'deg)';
}

使用setInterval定时器定时1000毫秒执行一次

这样就可以达到最终想要的效果了
在这里插入图片描述

三、时钟组件的调用

编写好时钟组件后,接下来就可以在页面上进行调用了

import clock from './components/clock'

export default {
  name: 'App',
  components: {
    clock
  }
}

调用<clock></clock>就能够将时钟放置到你想要的位置
因为之前设置了props的原因,所以可以通过简单的设置调整时钟的大小和颜色风格
<clock :bgsize="150" :bgcolor=color></clock>
color为#bec8e4

现在的时钟样式:
在这里插入图片描述




完整组件代码

<template>
    <!-- 时钟 -->
    <div class="clock" :style="styleVar">
        <!-- 内圈 -->
        <div class="innerBorder">
            <!-- 时钟刻度 -->
            <div class="scale mark1"></div>
            <div class="scale mark2"></div>
            <div class="scale mark3"></div>
            <div class="scale mark4"></div>
            <div class="scale mark5"></div>
            <div class="scale mark6"></div>
            <div class="scale mark7"></div>
            <div class="scale mark8"></div>
        </div>
        <!-- 内圈波浪 -->
        <div class="wave"></div>
        <!-- 时针、分针、秒针 -->
        <div class="hands hourhand"></div>
        <div class="hands minhand"></div>
        <div class="hands sechand"></div>
    </div>
</template>

<script>
export default {
    name: 'clock',
    components: {},
    props: {
        bgsize: {
            type: Number,
            default: 180
        },
        bgcolor: {
            type: String,
            default: '#D1CCC0'
        }
    },
    data() {
        return {
            hour: 0,  //小时
            minute: 0,  //分钟 
            second: 0,  //秒
        };
    },
    created() {},
    mounted() {
        this.currentTime();
        // 定时校准
        setInterval(this.currentTime, 1000);
    },
    watch: {},
    computed: {
        styleVar() {
            return {
                '--clock-size': this.bgsize + 'px',
                '--clock-bgcolor': this.bgcolor,
                '--length-log2E': ((this.bgsize - 10) / 2) / Math.LOG2E + 'px',
            }
        }
    },
    methods: {
        // 校准时钟指针方法
        currentTime:function(){
            let date = new Date();
            this.hour = date.getHours();
            this.minute = date.getMinutes();
            this.second = date.getSeconds();

            document.getElementsByClassName('hourhand')[0].style.transform = 'rotate(' + this.hour / 24 * 360 + 'deg)';
            document.getElementsByClassName('minhand')[0].style.transform = 'rotate(' + this.minute / 60 * 360 + 'deg)';
            document.getElementsByClassName('sechand')[0].style.transform = 'rotate(' + this.second / 60 * 360 + 'deg)';
        }
    },
};
</script>
<style scoped>
    /* 外部大小和阴影 */
    .clock {
        width: var(--clock-size);
        height: var(--clock-size);
        border-radius: 50%;
        box-shadow: 5px 5px 10px var(--clock-bgcolor), -4px -4px 8px #fff;
    }
    /* 内阴影 */
    .innerBorder {
        /* calc加var计算 */
        width: calc(var(--clock-size) - 10px);
        height: calc(var(--clock-size) - 10px);
        position: relative;
        left: 5px;
        top: 5px;
        box-shadow: -3px -3px 6px #fff inset, 3px 3px 6px var(--clock-bgcolor) inset;
        border-radius: 50%;
    }
    /* 时钟刻度 */
    .scale {
        width: 2px;
        height: 8px;
        position: absolute;
        box-shadow: 1px 1px 1px #9D958F inset, -1px -1px 1px var(--clock-bgcolor) inset;
        border-radius: 1px;
    }
    /* 设置小刻度位置 */
    .mark1 {
        left: calc(50% - 1px);
        top: 2px;
    }
    .mark2 {
        transform: rotate(45deg);
        left: calc(50% + var(--length-log2E) );
        top: calc(50% - var(--length-log2E) );
    }
    .mark3 {
        transform: rotate(90deg);
        left: calc(100% - 7px);
        top: calc(50% - 3px);
    }
    .mark4 {
        transform: rotate(135deg);
        left: calc(50% + var(--length-log2E) - 5px);
        top: calc(50% + var(--length-log2E) - 5px);
    }
    .mark5 {
        left: calc(50% - 1px);
        bottom: 2px;
    }
    .mark6 {
        transform: rotate(45deg);
        left: calc(50% - var(--length-log2E) + 5px);
        top: calc(50% + var(--length-log2E) - 5px);
    }
    .mark7 {
        transform: rotate(90deg);
        left: 2px;
        top: calc(50% - 3px);
    }
    .mark8 {
        transform: rotate(135deg);
        left: calc(50% - var(--length-log2E) );
        top: calc(50% - var(--length-log2E) );
    }
    /* 中间波浪 */
    .wave {
        width: 30%;
        height: 30%;
        position: absolute;
        left: 35%;
        top: 35%;
        box-shadow: 3px 3px 9px var(--clock-bgcolor), -3px -3px 9px #fff;
        border-radius: 50%;
        filter: blur(1px);  /* 模糊处理 */
        animation: wavemove 4s infinite linear; 
    }
    @keyframes wavemove {
        0% {
            transform: scale(0.5);
        }
        50% {
            transform: scale(1);
            opacity: 1;
        }
        100% {
            transform: scale(1.7);
            opacity: 0;
        }
    }
    /*************************** 时针、分针、秒针 ****************************/
    .hands {
        position: absolute;
        transform-origin: bottom;
        border-radius: 10px;
        z-index: 300;
        bottom: 50%;
        left: calc(50% - 1px);
    }  
    .sechand {
        width: 2px;
        height: 42%;
        background-image:  linear-gradient( #CD69C9, #1CA6F3);
    }
    .minhand {
        width: 4px;
        height: 33%;
        background-color: #9BA5AA;
        left: calc(50% - 2px);
    }
    .hourhand {
        width: 6px;
        height: 21%;
        background-color: #BEC8E4;
        left: calc(50% - 3px);
    }
</style>
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。