H5之canvas-绘制动态时钟

使用<canvas>元素不是非常难,但需要一些基本的HTML和JavaScript知识。

今天我们来利用canvas API绘制一个时钟,先上图:

画图之前,先把思路捋一遍:首先分解一下这个时钟的图形,它是由表盘(圆形)和指针(直线)组成。

canvas中圆形与矩形差距很大,canvas并没有提供专门绘制圆形的方法,但可以绘制圆弧,将圆弧首尾相连得到圆形

arc( x , y , radius , 起始弧度 , 结束弧度 , 旋转方向)
x,y --- 圆心坐标
radius --- 半径
弧度和角度的关系 --- 弧度 = 角度*Math.PI/180
例:2π是360°(完整的圆形)
旋转方向 --- true:逆时针;false:顺时针(默认)

掌握画圆大法后,就可以着手施工了:

首先准备好画布

<canvas id="myClock" width="500" height="500"></canvas>

接着获取上下文对象

var canvas = document.getElementById('myClock');
var con = canvas.getContext('2d');

分解功能:

1.表盘上的刻度(60个表示秒的刻度,12个表示小时的刻度)

1.1 60个秒刻度-->360°/60-->6°一个小格

//定义原点和半径
var x = 250;
var y = 250;
var r = 150;
con.moveTo(x,y);       
con.arc(x,y,r,0,6*Math.PI/180);
con.moveTo(x,y);
con.arc(x,y,r,6*Math.PI/180,12*Math.PI/180);
con.stroke();
……

先来做个小实验,以上代码片段将会得到这个图形

利用循环,将以上代码完善

//定义原点和半径
var x = 250;
var y = 250;
var r = 150;
//绘制秒刻度开始
con.beginPath();//为了不影响其他绘图,加上起始路径
for (var i = 0; i < 60; i++) {
    con.moveTo(x, y); //以圆心为起点
    con.arc(x, y, r, 6 * i * Math.PI / 180, 6 * (i + 1) * Math.PI / 180);//绘制一段6°的圆弧
}
con.closePath(); //为了不影响其他绘图,加上起始路径
con.stroke(); 

此刻,得到如下图形

怎么看怎么不像表盘咧?!为了达到秒刻度的效果,只需在上面覆盖一个较小的白色实心圆形即可

//较小的白色圆盘
con.beginPath();
con.moveTo(x,y);
con.arc(x,y,0.95*r,0,2*Math.PI);
con.closePath();
con.fillStyle = '#fff';//填充图形背景色
con.fill(); //实心圆

现在看上去,表盘的雏形算是出来了。

同样的步骤,将小时刻度也画出来,为了区分小时刻度和秒刻度,可以加粗小时刻度的线条

1.2 12个小时刻度-->360°/12-->30°一个大格

con.beginPath();//为了不影响其他绘图,加上起始路径
con.lineWidth = 4; //加粗小时刻度
for(var i = 0;i<12;i++){
    con.moveTo(x,y);
    con.arc(x,y,r,30*i*Math.PI/180,30*(i+1)*Math.PI/180);
}
con.closePath(); //为了不影响其他绘图,加上起始路径
con.stroke();

最后,再叠加一个较小的白色实心圆心,表盘就画完了(最难的部分也搞定了)

con.fillStyle = '#fff';
con.beginPath();
con.moveTo(x, y);
con.arc(x, y, 0.85 * r, 0, 2 * Math.PI);
con.closePath();
con.fill();

 总得来说,画表盘就和化妆一样,需要层层叠加

2.时、分、秒针

//注意:考虑到针要以圆心为中心旋转
con.lineWidth = 5; //定义时针线条的宽度
con.beginPath();
con.moveTo(x,y); //还是以圆心为起点
con.arc(x,y,0.5*r,0,0);//此处半径即时针的长度
con.closePath();
con.stroke();

分针和秒针就不做赘述,修改lineWidth的值和圆弧的半径即可

3.让时钟走起来

如何让秒针隔一秒动一下呢?是不是很快想到这个方法--->setInterval()

……
//获取当前系统时间
var today = new Date();
var hh = today.getHours();
var mm = today.getMinutes();
var ss = today.getSeconds();
//时针对应的弧度
var hhVal = (-90 + hh * 30 + mm / 2)*Math.PI/180;
//-90:canvas画圆的起始点在表盘的3个字,而时钟的起始点应在12个字。+mm/2:时针不会一直只在整点的位置,分针走30分钟,时针多走15°
var mmVal = (-90 + mm * 6) * Math.PI / 180;
var ssVal = (-90 + ss * 6) * Math.PI / 180;
……
con.arc(x, y, 0.5 * r, hhVal, hhVal);
……
//调用函数
setInterval(toDraw, 1000);

组合好代码后,时钟就能走起来了:(^-^)V

奉上完整代码:

HTML部分

<canvas id="myClock" width="500" height="500"></canvas>
<p id="showDate"></p>

JavaScript部分

        window.onload = function () {
            //获取上下文对象
            var canvas = document.getElementById('myClock');
            var con = canvas.getContext('2d');
            //自定义函数---画表盘,针
            function toDraw() {
                //定义原点和半径
                var x = 250;
                var y = 250;
                var r = 150;
                //绘制秒刻度开始
                con.beginPath();
                for (var i = 0; i < 60; i++) {
                    con.moveTo(x, y);//以圆心为起点
                    con.arc(x, y, r, 6 * i * Math.PI / 180, 6 * (i + 1) * Math.PI / 180);//绘制一段6°的圆弧
                }
                con.closePath(); //为了不影响其他绘图,加上起始路径
                con.stroke();
                //较小的白色圆盘
                con.fillStyle = '#fff';
                con.beginPath();
                con.moveTo(x, y);
                con.arc(x, y, 0.95 * r, 0, 2 * Math.PI);
                con.closePath();
                con.fill(); //实心圆
                //绘制秒刻度结束
                //同理绘制小时刻度
                con.beginPath();
                con.lineWidth = 4; //加粗小时刻度
                for (var i = 0; i < 12; i++) {
                    con.moveTo(x, y);
                    con.arc(x, y, r, 30 * i * Math.PI / 180, 30 * (i + 1) * Math.PI / 180);
                }
                con.closePath(); //为了不影响其他绘图,加上起始路径
                con.stroke();
                //较小的白色圆盘
                con.fillStyle = '#fff';
                con.beginPath();
                con.moveTo(x, y);
                con.arc(x, y, 0.85 * r, 0, 2 * Math.PI);
                con.closePath();
                con.fill();
                //绘制小时刻度结束

                //获取当前系统时间
                var today = new Date();
                var hh = today.getHours();
                var mm = today.getMinutes();
                var ss = today.getSeconds();
                document.getElementById('showDate').innerHTML = hh+':'+mm+':'+ss;
                //时针对应的弧度
                var hhVal = (-90 + hh * 30 + mm / 2) * Math.PI / 180;
                var mmVal = (-90 + mm * 6) * Math.PI / 180;
                var ssVal = (-90 + ss * 6) * Math.PI / 180;
                //开始绘制时、分、秒针(注意:考虑到针要以原点为中心旋转)
                con.lineWidth = 5; //时针
                con.beginPath();
                con.moveTo(x, y);
                con.arc(x, y, 0.5 * r, hhVal, hhVal);
                con.closePath();
                con.stroke();
                con.lineWidth = 3; //分针
                con.beginPath();
                con.moveTo(x, y);
                con.arc(x, y, 0.65 * r, mmVal, mmVal);
                con.closePath();
                con.stroke();
                con.lineWidth = 1; //秒针
                con.beginPath();
                con.moveTo(x, y);
                con.arc(x, y, 0.8 * r, ssVal, ssVal);
                con.closePath();
                con.stroke();
            }
            //每隔1秒调用一次函数
            setInterval(toDraw, 1000);
        }    
原文地址:https://www.cnblogs.com/laoli-note/p/11330332.html