canvas实现挂钟,实现该效果不难,只是实现过程帮助我们更好的掌握几个知识点。
照例先奉上效果图:
<div id="block">
<canvas id="bgcan" width="250" height="250"></canvas>
<canvas id="clockcan" width="200" height="200"></canvas>
</div>
div设置整个背景图。
这里采用两个canvas,均是绝对定位。id分别为bgcan , clockcan:
这里在bgcan上绘制挂钟的钟框。也就是外部的圆环。
在clockcan上绘制各时间点及时针、分针、秒针。
首先取得和定义需要的元素和变量:
var bgcan = document.getElementById("bgcan"),
clockcan = document.getElementById("clockcan"),
bgcontext = bgcan.getContext("2d"),
clockcontext = clockcan.getContext("2d"),
bgX = bgcan.width/2,
bgY = bgcan.height/2,
clockX = clockcan.width/2,
clockY = clockcan.height/2,
radius = clockcan.width/2-20;
绘制外部的钟框:
var radgrad = bgcontext.createRadialGradient(bgX,bgY,bgcan.width/2-50,bgX,bgY,bgcan.width/2);
radgrad.addColorStop(0,"#BEBAB7");
radgrad.addColorStop(1/5,"#ffffff");
radgrad.addColorStop(2/5,"#BFBBBA");
radgrad.addColorStop(3/5,"#EEEEEC");
radgrad.addColorStop(4/5,"#EBEBEB");
radgrad.addColorStop(1,"#EEEEEC");
bgcontext.fillStyle = radgrad;
bgcontext.fillRect(0,0,bgcan.width,bgcan.height);
这里涉及第一个知识点:绘制径向渐变
首先使用createRadialGradient方法创建canvasGradient对象,然后使用addColorStop方法上色。
其中createRadialGradient(x1 , y1 , r1 , x2 , y2 , r2)参数含义:
定义一个以x1,y1为原点,半径为r1的圆,再定义一个以x2,y2为原点,r2为半径的圆。
接下来绘制另一个画布上的内容:
首先初始化样式:
clockcontext.font = "normal 24px Arial";//设置字体样式
clockcontext.translate(clockX,clockY);//设置坐标原点在该画布中心
绘制每一个时间点(60个秒点):
for (var i = 0,angle=0; i < 60; i++) {
clockcontext.save();
clockcontext.beginPath();
clockcontext.moveTo((radius+18)*Math.cos(angle),(radius+18)*Math.sin(angle));
if (i%5==0) {
clockcontext.lineWidth = 3;
}
clockcontext.lineTo((radius+13)*Math.cos(angle),(radius+13)*Math.sin(angle));
clockcontext.stroke();
clockcontext.restore();
angle += Math.PI/30;
}
这里根据角度来取得每个点对应坐标,遇到分点时(i%5),点的宽度增粗。
绘制每个时刻:
for (var i = 1; i < 13; i++) {
timeText(i,radius*Math.sin(Math.PI*i/6),-radius*Math.cos(Math.PI*i/6));//调用timeText(时刻,对应横坐标,对应纵坐标)函数绘制
}
function timeText(num,x,y){
clockcontext.save();
x -= (clockcontext.measureText(num).width/2);
y += 8;
clockcontext.beginPath();
clockcontext.translate(x,y);
clockcontext.fillText(num,0,0);
clockcontext.restore();
}
第二个知识点:measureText方法获得指定字符串,返回一个TextMetrics对象,该对象的width属性表示使用当前指定的字体后该字符串总文字的宽度。
第三个知识点:绘制文字有两个方法:
fillText(text , x, y ,[maxWidth]);填充绘制文字,四个参数依次表示表示所绘文字,文字起点对应横坐标,文字起点对应纵坐标,文字最大宽度(可选)。
strokeText(text , x, y ,[maxWidth]);轮廓绘制文字。参数意义相同。
取得当前时间:
var time = new Date(),
timeH = time.getHours(),
timeM = time.getMinutes(),
timeS = time.getSeconds();
if (timeH > 12) {
timeH -= 12;
}
更新绘制时针、分针、秒针:
// h、m、s分别为所取得当前时、分、秒数值。
function update(h,m,s){
//绘制中心的小圆,使得更形象
clockcontext.save();
clockcontext.beginPath();
clockcontext.moveTo(0,0);
clockcontext.fillStyle = "#222";
clockcontext.arc(0,0,8,0,Math.PI*2,false);
clockcontext.fill();
clockcontext.restore();
//绘制时针
clockcontext.save();
clockcontext.beginPath();
clockcontext.moveTo(0,0);
clockcontext.lineWidth = 10;
clockcontext.lineCap = "round";//设置端点样式
clockcontext.lineTo((radius-35)*Math.cos(Math.PI*(h-3)/6),(radius-35)*Math.sin(Math.PI*(h-3)/6));
clockcontext.stroke();
clockcontext.restore();
//绘制分针
clockcontext.save();
clockcontext.beginPath();
clockcontext.moveTo(0,0);
clockcontext.lineWidth = 5;
clockcontext.lineTo((radius-5)*Math.cos(Math.PI*(m-15)/30),(radius-5)*Math.sin(Math.PI*(m-15)/30));
clockcontext.stroke();
clockcontext.restore();
//绘制秒针
clockcontext.save();
clockcontext.beginPath();
clockcontext.fillStyle = "#222";
clockcontext.rotate(Math.PI*(s-15)/30);
clockcontext.moveTo(-40,-2);
clockcontext.lineTo(-40,2);
clockcontext.lineTo(-1,2);
clockcontext.lineTo(0,1);
clockcontext.lineTo(radius+15,1);
clockcontext.lineTo(radius+15,-1);
clockcontext.lineTo(0,-1);
clockcontext.lineTo(0,-2);
clockcontext.lineTo(-40,-2);
clockcontext.fill();
clockcontext.restore();
}
注意这里绘制秒针的方式有点不同,看效果图秒针的底部还多出来一节,想要实现这种效果,可以先把坐标空间旋转,使横坐标轴由圆心指向当前秒数所在坐标,随之依次绘制各坐标点,即可实现效果。
编写一个时间更新函数:
function updateTime(){
var time = new Date(),
timeH = time.getHours(),
timeM = time.getMinutes(),
timeS = time.getSeconds();
alert(timeH);
if (timeH > 12) {
timeH -= 12;
}
//每次更新都需要先清理当前画布
clockcontext.clearRect(-clockcan.width/2,-clockcan.height/2,clockcan.width,clockcan.height);
drawTime();//绘制各时间点函数(将以上绘制时间点代码和各时刻代码封装成一个函数)
update(timeH,timeM,timeS);
}
最后调用setInterval方法每隔一秒执行一次时间更新函数:
setInterval("updateTime()",1000);
完整代码下载地址:canvas实现挂钟。