Canvas简易时钟

47次阅读

共计 2854 个字符,预计需要花费 8 分钟才能阅读完成。

先看下显示结果:

参考:

1:Canvas 绘制时钟

2:canvas 动画时钟

3:HTML 5 canvas lineCap 属性

4:HTML5 canvas arc() 方法

5:Window.requestAnimationFrame()

6:window.cancelAnimationFrame()

好了进入正题;参考了上面的这些内容后,自己也动手也写一个简易的时钟吧。
首先抓住关键知识:
1:小时是 24 小时制的,所以在这里我们需要把小时改成 12 小时制

hr = hr >= 12 ? hr - 12 : hr;

2:画小时数字时的角度问题
参考了此图:

可以看出:

x = r * cos(角度)
y = r * sin(角度)

三角函数知识来一波:
sin(a) = BC/AC;
cos(a) = AB/AC;

故得到以下角度代码:

var x = Math.cos(rad) * (r / 2 - 40);
var y = Math.sin(rad) * (r / 2 - 40);

3:将坐标轴逆时针旋转 90 度,x 轴正方向对准 12 点方向

ctx.rotate(-Math.PI / 2);

4:画时针(小时刻度为:小时(12h)+ 分钟(60x60min)+ 秒(3600×12=21600s))

ctx.rotate(hr * (Math.PI / 6) + (Math.PI / 360) * min + (Math.PI / 21600) * sec);

5:画分针(分针刻度为:分针(60)m + 秒(60×60)s)

ctx.rotate((Math.PI / 30) * min + (Math.PI / 1800) * sec);

6:requestAnimationFrame(更新动画)

具体代码如下

<body onload="draw()">
    <canvas height='500' width='500' id='tutorial'></canvas>
    <script>
        function draw() {var tutorial = document.getElementById('tutorial'),
                tutorialw = tutorial.width,
                date = new Date(),
                sec = date.getSeconds(),
                min = date.getMinutes(),
                hr = date.getHours();
            hr = hr >= 12 ? hr - 12 : hr;
            if (tutorial.getContext) {var ctx = tutorial.getContext('2d'),
                    r = tutorialw / 2;
                // 繪製 outer circle
                ctx.save();
                ctx.clearRect(0, 0, 500, 500);
                ctx.translate(r, r);
                ctx.lineCap = 'round';// 属性设置或返回线条末端线帽的样式。butt: 默認 round:向线条的每个末端添加圆形线帽。square:向线条的每个末端添加正方形线帽。ctx.beginPath();
                ctx.arc(0, 0, 140, 0, Math.PI * 2, true);
                ctx.moveTo(0, 0);
                ctx.arc(0, 0, 5, 0, Math.PI * 2, true);
                ctx.lineWidth = 7;
                ctx.strokeStyle = '#283b28';
                ctx.closePath();
                ctx.stroke();
                // 画小时数
                var hours = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
                for (var h in hours) {
                    var rad = 2 * Math.PI / 12 * h;
                    var x = Math.cos(rad) * (r / 2 - 40);
                    var y = Math.sin(rad) * (r / 2 - 40);
                    ctx.font = "20px Georgia";
                    ctx.textAlign = "center";
                    ctx.textBaseline = "middle";
                    ctx.fillText(hours[h], x, y);
                }
                ctx.rotate(-Math.PI / 2);// 将坐标轴逆时针旋转 90 度,x 轴正方向对准 12 点方向
                //Minute scale
                ctx.save();
                for (var i = 0; i < 60; i++) {ctx.beginPath();
                    ctx.rotate(Math.PI / 30);// 每个 6deg 画一个时钟刻度线
                    ctx.moveTo(110, 0);
                    ctx.lineTo(110, 0);
                    ctx.lineWidth = 5;
                    ctx.strokeStyle = '#fba615';
                    ctx.closePath();
                    ctx.stroke();}
                ctx.restore();
                //Hour scale
                ctx.save();
                for (var i = 0; i < 12; i++) {ctx.beginPath();
                    ctx.rotate(Math.PI / 6);// 每个 30deg 画一个时钟刻度
                    ctx.moveTo(100, 0);
                    ctx.lineTo(120, 0);
                    ctx.lineWidth = 5;
                    ctx.closePath();
                    ctx.stroke();}
                ctx.restore();
                //sec start
                ctx.save();
                ctx.beginPath();
                ctx.rotate(Math.PI / 30 * sec);
                ctx.moveTo(0, 0);
                ctx.lineTo(45, -5);
                ctx.lineTo(50, 10);
                ctx.lineTo(80, 0);
                ctx.lineWidth = 3;
                ctx.strokeStyle = '#7d9561';
                ctx.moveTo(90, 0);
                ctx.arc(85, 0, 5, 0, Math.PI * 2, true);
                ctx.strokeStyle = '#7d9561';
                ctx.closePath();
                ctx.stroke();
                ctx.restore();
                //min start
                ctx.save();
                ctx.beginPath();
                ctx.rotate((Math.PI / 30) * min + (Math.PI / 1800) * sec);
                ctx.moveTo(0, 0);
                ctx.lineTo(85, 0);
                ctx.lineWidth = 8;
                ctx.strokeStyle = '#283b28';
                ctx.closePath();
                ctx.stroke();
                ctx.restore();
                //hour start
                ctx.save();
                ctx.beginPath();
                ctx.rotate(hr * (Math.PI / 6) + (Math.PI / 360) * min + (Math.PI / 21600) * sec);
                ctx.moveTo(0, 0);
                ctx.lineTo(70, 0);
                ctx.lineWidth = 8;
                ctx.strokeStyle = '#ff8b17';
                ctx.closePath();
                ctx.stroke();
                ctx.restore();
                ctx.restore();}
            window.requestAnimationFrame(draw);
        }
        window.requestAnimationFrame(draw);
    </script>
</body>

正文完
 0