昨天过了一遍canvas的基本用法,今天来写个小小的案例练练手吧。
用canvas 画一个时钟,效果图如下:
额。。。。配色好像有点丑,那个不是重点,,,嘻嘻~
在开始写之前,我们先来考虑一下总共分为几个步骤:
1.首先要先画一个背景作为钟表的表盘。比较简单。。
2.背景图画好之后,我们开始画钟表的刻度线,刻度线又分为分刻度和时刻度。
3.刻度线和表盘都是不动的,画完精止的部分接下来就是动态改变的部分,即指针。
不论多么困难得问题,都是由一个个的小问题堆起来的,我们开始一个个解决。
1.画背景:
背景这部分可以用cilp方法实现。我的画布大小为420*420,这个看个人爱好。半径为200,将圆心坐标定在画布中心,画好圆之后,调用clip(),对画布进行切割,圆外的部分便不可以进行绘制。最后用drawImage()将图片绘制成功。
ctx.beginPath();
ctx.arc(210,210,200,0,2*Math.PI,true);
ctx.strokeStyle = '#59A0C5';
ctx.lineWidth = 5;
ctx.stroke();
ctx.clip();
ctx.closePath();
var img = document.createElement('img');
img.src = "1.jpg";
ctx.beginPath();
ctx.drawImage(img,0,0,420,420);
ctx.closePath();
2.画刻度
画时针的刻度和分针的刻度其实是相同的道理。可以先将画布的原点移动到圆心处,然后用moveto和lineto画出一条刻度线。然后对画布进行旋转,进而画出所有的刻度。
在这里我们需要注意的是,一旦对画布进行了旋转,下次对画布进行绘制的时候,将会以旋转之后的画布为标准。
我们可以试想一下,画完第一条刻度后,我们将画布旋转6度绘制第二条刻度,第三条旋转时将会按照第二次旋转之后的画布为标准继续旋转,不利于我们进行角度的计算。这个时候便可以用到canvas的save()和restore()方法,在每一次绘画之前先保存一下画布状态,每画完一条调用一次restore函数,吧画布恢复为初始状态,这样便可以保证每次绘制的时候画布都是处在一开始的状态。
代码如下:
//分刻度
for(var i=0;i<60;i++){
ctx.save();
ctx.beginPath();
ctx.translate(210,210);
ctx.rotate(i*6*Math.PI/180);
ctx.strokeStyle = '#50F4F8';
ctx.lineWidth = 3;
ctx.moveTo(0,-195);
ctx.lineTo(0,-205);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
//时刻度
for(var i=0;i<12;i++){
ctx.save();
ctx.beginPath();
ctx.translate(210,210);
ctx.rotate(i*30*Math.PI/180);
ctx.strokeStyle = '#425AF2';
ctx.lineWidth = 5;
ctx.moveTo(0,-185);
ctx.lineTo(0,-205);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
3.画指针
画好了刻度,我们再来画指针。钟表的指针会每秒钟发生改变。所以要想实现这个效果,便需要一个计时器,每一秒钟画一次。只要我们知道了这一秒每一个指针应该相对于初始状态旋转的度数,我们便可以绘制出对应的指针。
var dates = new Date(); //获取当前时间
var h = dates.getHours(); //获取小时数
var m = dates.getMinutes(); //获取分钟数
var s = dates.getSeconds(); //获取秒数
h = h+m/60; //当前的小时数
m = m + s/60; //当前的分钟数
得到了当前的h,m,s的数值,我们便得到了时针,分针和秒针的旋转度数。
时针旋转度数:h × 30
分针旋转度数:m × 6
秒针旋转度数:s × 6
//画时针
ctx.save();
ctx.beginPath();
ctx.translate(210,210);
ctx.rotate(h*30*Math.PI/180);
ctx.strokeStyle = '#2B8AF8';
ctx.lineWidth = 5;
ctx.moveTo(0,14);
ctx.lineTo(0,-100);
ctx.stroke();
ctx.closePath();
ctx.restore();
//分针
ctx.save();
ctx.beginPath();
ctx.translate(210,210);
ctx.rotate(m*6*Math.PI/180);
ctx.strokeStyle = '#50F4F8';
ctx.lineWidth =3;
ctx.moveTo(0,14);
ctx.lineTo(0,-130);
ctx.stroke();
ctx.closePath();
//秒针
ctx.save();
ctx.beginPath();
ctx.translate(210,210);
ctx.rotate(s*6*Math.PI/180);
ctx.strokeStyle = '#F61538';
ctx.lineWidth =3;
ctx.moveTo(0,14);
ctx.lineTo(0,-160);
ctx.stroke();
ctx.closePath();
4.其他
为了美观,我们还可以在表盘中心和秒针末端加上两个圆
//中心圆
ctx.beginPath();
ctx.fillStyle = '#50F4F8';
ctx.strokeStyle = '#F61538';
ctx.lineWidth =3;
ctx.arc(0,0,7,0,2*Math.PI,true);
ctx.fill();
ctx.stroke();
ctx.closePath();
//秒针上的圆
ctx.beginPath();
ctx.fillStyle = '#50F4F8';
ctx.strokeStyle = '#F61538';
ctx.lineWidth =3;
ctx.arc(0,-150,5,0,2*Math.PI,true);
ctx.fill();
ctx.stroke();
ctx.closePath();
ctx.restore();
这样,我们便把时钟的每一部分都绘制完了,现在只需要讲每一部分的绘制合并在一起,封装在一个函数中,通过计时器调用绘制即可。