likes
comments
collection
share

canvas 实现多彩的圆环数字时钟

作者站长头像
站长
· 阅读数 43

前言

最近在学习 canvas 的道路上一去不复返,刚好又在小破站学到了一个时钟效果,虽然之前也开发过相关的内容,但是这次的内容会比之前的更加有趣,依旧是使用 canvas 来实现,不同的是这次实现的方法跟以往有很大的区别。老规矩,先来看一下最终的实现效果,如图所示:

canvas 实现多彩的圆环数字时钟

效果很简单,圆环时钟的时分秒都展示不同的颜色,并且中间时间的颜色还会根据当前时间的变化而变化,下面就跟着我一起来看一下如何实现这个多彩的圆环时钟吧!

圆环

上一篇文章中,我们通过 canvasctx.arc() 方法绘制了多个炫彩的动态圆环,而这一节要实现这个圆环数字时钟,依旧需要使用到 ctx.arc() 方法。

首先我们还是先来编写相关的 htmlcss,因为这一节的内容跟前面的文字有些不一样,因此我们这里还是给出完整的 htmlcss 代码,如下:

<canvas id="canvas"></canvas>
<div id="clock"></div>

可以看到 html 中除了有一个 canvas 标签外,还多了一个 idclockdiv 标签,它主要是为了实现中间数字时间而准备的。接下来我们再一起来看 css 相关的代码,如下:

*{margin: 0; padding: 0;}
body {
    background: #333;
    width: 100%;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
}
#clock {
    position: absolute;
    font-size: 50px;
    font-weight: bold;
    font-family: Arial, Helvetica, sans-serif;
}

css 相关的内容也很简单,主要是将 body 设置为 flex 布局,实现上下左右居中对齐,让页面中的所有元素都居中显示。接下来就该来实现 js 相关的内容了,这次我们依旧跟前面的文章一样,采用 TS + ES6 的写法来开发。

还是跟前面的文章中描述的一样,我们首先定义一个 Clock 类,通过面向对象的方法来实现这个圆环时钟的效果,初始化的代码如下:

class Clock {
    canvas: HTMLCanvasElement;
    ctx: CanvasRenderingContext2D;
    clock: HTMLElement;
    constructor() {
        this.canvas = document.getElementById('canvas') as HTMLCanvasElement;
        this.clock = document.getElementById('clock') as HTMLElement;
        this.ctx = this.canvas.getContext('2d');
        this.canvas.width = 400;
        this.canvas.height = 400;
    }
}

Clock 类的 constructor 函数中,我们定义了 canvas 的宽和高都是 400,这是因为我们要实现的圆环时钟不需要很大,当然你也可以自己随意的设置 canvas 的大小,这根据个人的喜好来就可以了。有了初始的内容,接下来我们就先将时钟的外部圆环画出来,那该如何实现呢?

在我们实现的所有 canvas 效果中,最常定义的两个函数分别是 drawupdate,这两个函数一般用于绘制和更新,在这个效果中同样也不例外。我们先来定义一个 draw 函数,然后在这个函数中将圆环时钟的三个圈先画出来,具体代码如下:

class Clock {
    ...other code
    
    draw() {
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
        const date = new Date();
        // 根据当前时间获取时分秒对应的角度
        // 每秒角度变化为6度,每毫秒角度变化为6/1000度
        const secdeg = date.getSeconds() * 6 + date.getMilliseconds() * 6 / 1000;
        const mindeg = date.getMinutes() * 6 + secdeg / 60;
        // 小时转换为12小时制
        const hourdeg = date.getHours() % 12 * 30 + mindeg / 60;
        const lines = [hourdeg, mindeg, secdeg];
        this.ctx.lineWidth = 10;
        this.ctx.lineCap = 'round';
        
        for (let i = 0; i < 3; i++) {
            // 渲染表盘(底色)
            this.ctx.beginPath();
            this.ctx.arc(200, 200, 140 + i * 20, 0, Math.PI * 2);
            this.ctx.strokeStyle = `hsl(210deg, 30%, 10%)`;
            this.ctx.stroke();

            // 渲染表带(走的时间)
            this.ctx.beginPath();
            this.ctx.arc(200, 200, 140 + i * 20, -Math.PI / 2, Math.PI / 180 * lines[i] - Math.PI / 2, false);
            this.ctx.strokeStyle = `hsl(${i * 120}deg, 45%, 60%)`;
            this.ctx.stroke();
        }
    }
    
    animate() {
        requestAnimationFrame(() => this.animate());
        this.draw();
    }
}

draw 方法中,我们需要借助 Date 这个对象来获取当前是时间,并根据当前的时分秒来生成对应的角度,最后通过循环动态的绘制出时分秒的三个圆环,通过上述的代码,最终实现的效果如下所示:

canvas 实现多彩的圆环数字时钟

可以看到我们已经将时分秒的三个圆环绘制出来了,但是目前还看不出这是一个时钟,因此我们还需要添加最外层的刻度盘,方便我们知道当前的大概时间,修改 draw 方法即可,相关代码如下:

class Clock {
    ...other code
    
    draw() {
        ...other code
        
        for (let i = 0; i < 12; i++) {
            const bx = 200 + 180 * Math.cos(i * 30 * Math.PI / 180);
            const by = 200 + 180 * Math.sin(i * 30 * Math.PI / 180);
            this.ctx.fillStyle = '#6fd08c';
            this.ctx.beginPath();
            this.ctx.arc(bx, by, 3, 0, Math.PI * 2);
            this.ctx.fill();
        }
    }
}

再次循环 12次,获取到每个刻度的位置,然后依旧通过 ctx.arc() 方法来将这些圆点绘制在对应的刻度上,最终实现的效果如下所示:

canvas 实现多彩的圆环数字时钟

通过上图可以看出,每个刻度是5秒钟,而一分钟是60秒,因此我们需要循环12次来渲染出这些刻度来。

光有刻度还不行,因为还无法准确的看出当前的时间,所以我们还需要继续来改造 draw 方法才行。还记得我们在 html 中添加的 idclockdiv 元素吗?它就是用来做电子时钟的显示用的,让我们一起来看代码,如下:

class Clock {
    ...other code
    
    draw() {
        ...other code
        
        const x = Math.cos((secdeg + 90) * Math.PI / 180);
        const y = Math.sin((secdeg + 90) * Math.PI / 180);
        this.clock.style.textShadow = `${x}px ${y}px 5px hsl(${mindeg | 0}, 50%, 70%)`;
        this.clock.style.color = `hsl(${secdeg | 0}, 50%, 80%)`;
        this.clock.innerText = `${('0' + date.getHours()).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}:${('0' + date.getSeconds()).slice(-2)}`;
    }
}

draw 方法的最后,我们通过获取到的 div 标签,设置它的 textShadow 属性,也就是文字的阴影,然后给文字添加对于的 color 值,最后再通过 innerText 这个 api 来给 div 标签设置对应的文字。这里依旧用的是前面的 Date 对象,通过 Date 对象的相关 api 来获取当前的时分秒,从而实现我们最终的圆环数字时钟效果。

完整的代码及效果可以在这里查看:

总结

这篇文章的实现非常的简单,但是其中包含的知识点还是非常多的,先不说 canvas 相关的操作,对于 Date 对象的使用,我们也应该格外的注意,因为在实际的开发中,我们需要经常与 Date 对象打交道,因此还是要对 Date 对象有一定的了解才行。

最后,如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者,谢谢大家

往期回顾

不得不说,这个 canvas 的旋转半圆效果可能会闪瞎你的双眼🐶

canvas 实现燃烧的线段,原来线段也能玩的这么出彩

又实现了一个酷炫的动感激光,不来看看?

canvas 动画真好玩,快来学一下这炫酷的效果吧!

妙啊,canvas 还能实现这么酷炫的旋转六边形

为了学会更多炫酷的 canvas 效果,我熬夜复习了三角函数相关的知识点

嚯,五角星还能这么玩?快摘下来送给你的她/他/ta😁

这个国庆,带老婆去看一场烟花雨

转载自:https://juejin.cn/post/7156740899991453710
评论
请登录