效果图
http://www.hui12.com/nbin/csdn/canvasClock/demo.html
https://nbin2008.github.io/demo/canvasClock/index.html
html代码
js代码
(function(window){
var proto = {
init: function(e){
this.before(e);
this.start();
},
before: function(e){
this.canvas = e.canvas;
},
start: function(){
var This = this;
var mycanvas = this.canvas;
var width = mycanvas.width;
var height = mycanvas.height;
var myc = mycanvas.getContext("2d");
var coords = [];
setcoords();
draw();
setInterval(draw,1000);
function draw(){
//绘制点
myc.clearRect(0, 0, width, height);
myc.lineCap = 'round';
myc.beginPath();
myc.fillStyle = "#000";
myc.arc(width/2, height/2, height/2, 0, 2*Math.PI);
myc.fill();
myc.beginPath();
myc.fillStyle = "#fff";
myc.arc(width/2, height/2, height/2*0.9, 0, 2*Math.PI);
myc.fill();
for( var i=0; i<coords.length; i++ ){
myc.beginPath();
var tmp = coords[i];
myc.moveTo(tmp[0], tmp[1]);
myc.lineTo(tmp[2], tmp[3]);
myc.strokeStyle = "#000";
myc.lineWidth = tmp[4]?width*0.02:width*0.01;
myc.stroke();
};
//绘制指针
var tmp = getPoint();
for( var i=0, l=tmp.length; i<l; i++ ){
myc.beginPath();
myc.moveTo(tmp[i][0],tmp[i][1]);
myc.lineTo(tmp[i][2],tmp[i][3]);
if( i == 0 ){
myc.lineWidth = width*0.03;
}else if( i==1 ){
myc.lineWidth = width*0.02;
}else if( i==2 ){
myc.lineWidth = width*0.01;
}
myc.strokeStyle = "#000";
myc.shadowBlur = 4;
myc.shadowColor = "#fff";
myc.stroke();
//指针圆
if( i==2 ){
myc.beginPath();
var x = tmp[i][4];
var y = tmp[i][5];
myc.arc(x, y, width*0.03, 0 , 2*Math.PI);
myc.fillStyle = "#fff";
myc.fill();
myc.strokeStyle = "#000";
myc.stroke();
};
};
//绘制中心圆
myc.beginPath();
myc.arc(width/2, height/2, width*0.03/2, 0 ,2*Math.PI);
myc.fillStyle = "#fff";
myc.fill();
myc.beginPath();
myc.arc(width/2, height/2, width*0.018/2, 0 ,2*Math.PI);
myc.fillStyle = "#000";
myc.fill();
myc.beginPath();
myc.arc(width/2, height/2, width*0.005/2, 0 ,2*Math.PI);
myc.fillStyle = "#fff";
myc.fill();
};
function setcoords(){
var r1 = height/2*0.85;
var r2 = height/2*0.8;
var r3 = height/2*0.75;
for( var i=1; i<61; i++ ){
var angle = i*6*Math.PI/180;
var x1 = width/2 + r1*Math.sin(angle);
var y1 = height/2 - r1*Math.cos(angle);
var x2 = width/2 + r2*Math.sin(angle);
var y2 = height/2 - r2*Math.cos(angle);
var tmp = [x1, y1, x2, y2];
if( i%5 == 0 ){
x2 = width/2 + r3*Math.sin(angle);
y2 = height/2 - r3*Math.cos(angle);
tmp.splice(2,1,x2);
tmp.splice(3,1,y2);
tmp.push(1);
};
coords.push(tmp);
};
};
function getPoint(){
var angle = getTimeAngle();
var bLength = 0.05*width;
var hX1 = width/2 + bLength*Math.sin( (angle.h+180)*Math.PI/180 );
var hY1 = width/2 - bLength*Math.cos( (angle.h+180)*Math.PI/180 );
var hX2 = width/2 + 0.15*width*Math.sin( angle.h*Math.PI/180 );
var hY2 = height/2 - 0.15*width*Math.cos( angle.h*Math.PI/180 );
var mX1 = width/2 + bLength*Math.sin( (angle.m+180)*Math.PI/180 );
var mY1 = width/2 - bLength*Math.cos( (angle.m+180)*Math.PI/180 );
var mX2 = width/2 + 0.28*width*Math.sin( angle.m*Math.PI/180 );
var mY2 = height/2 - 0.28*width*Math.cos( angle.m*Math.PI/180 );
var sX1 = width/2 + bLength*Math.sin( (angle.s+180)*Math.PI/180 );
var sY1 = width/2 - bLength*Math.cos( (angle.s+180)*Math.PI/180 );
var sX2 = width/2 + 0.35*width*Math.sin( angle.s*Math.PI/180 );
var sY2 = height/2 - 0.35*width*Math.cos( angle.s*Math.PI/180 );
var rX1 = width/2 + 0.28*width*Math.sin( angle.s*Math.PI/180 );
var rY1 = height/2 - 0.28*width*Math.cos( angle.s*Math.PI/180 );
return [
[hX1, hY1, hX2, hY2],
[mX1, mY1, mX2, mY2],
[sX1, sY1, sX2, sY2, rX1, rY1]
];
};
function getTimeAngle(){
var now = new Date();
var s = now.getSeconds();
var m = now.getMinutes() + s/60;
var h = (now.getHours()>=12?now.getHours()-12:now.getHours()) + m/60;
return {
h: h*30,
m: m*6,
s: s*6
};
};
}
};
function Clock(e){
this.init(e)
};
Clock.prototype = proto;
Clock.prototype.constructor = Clock;
window.Clock = Clock;
})(window);
逻辑部分:
myc是获取canvas绘图环境
width,height是等值,因为绘图都是以圆心为基准,所以要用到
coords = [] 标记时间的点都是小的线段,起点和终点,所以数组结构为2次数组,[ [x1,y1,x2,y2] ... ],当5分,10分这些长时间点,额外添加一个参数,绘图时加粗
setcoords() 设置时间点函数
function setcoords(){
var r1 = height/2*0.85;<span style="white-space:pre"> </span>//height/2,为绘图环境高度的一半,用来设置圆的半径(时间点的轨迹),*0.85,因为时钟外面有圆圈,所以缩小
var r2 = height/2*0.8;<span style="white-space:pre"> </span>//获取短点的的假数值
var r3 = height/2*0.75;<span style="white-space:pre"> </span>//获取长点的假数值
for( var i=1; i<61; i++ ){
var angle = i*6*Math.PI/180;<span style="white-space:pre"> </span>//时间点之间共用60个小格,每个小格的弧度为6,角度转弧度 *π/180;
var x1 = width/2 + r1*Math.sin(angle);<span style="white-space:pre"> </span>//以0点为例,获取0点的头部x坐标,加width/2,是因为canvas绘图环境都是默认左上角为基点
var y1 = height/2 - r1*Math.cos(angle);<span style="white-space:pre"> </span>//获取头部y坐标
var x2 = width/2 + r2*Math.sin(angle);<span style="white-space:pre"> </span>//获取底部x坐标
var y2 = height/2 - r2*Math.cos(angle);<span style="white-space:pre"> </span>//获取底部y坐标
var tmp = [x1, y1, x2, y2];
if( i%5 == 0 ){<span style="white-space:pre"> </span>//这里为五分,十分的时间点,比常规的时间点要长,数据替换,额外添加一个参数
x2 = width/2 + r3*Math.sin(angle);
y2 = height/2 - r3*Math.cos(angle);
tmp.splice(2,1,x2);
tmp.splice(3,1,y2);
tmp.push(1);
};
coords.push(tmp);<span style="white-space:pre"> </span>//到这里,coords的数据就完成了
};
};
这个函数是获取指针的坐标
bLength 为端点值,等下用来获取绘图起点,如果端点设置为圆心,这部就可以省略了。
h,m,s分别对应时针,分针,秒针,这是获取指针坐标的函数
以时针为例。
因为秒针上有一个圆圈,所以额外增加参数。
数据都设置完毕,现在开始绘图start函数
//绘制点
myc.clearRect(0, 0, width, height);
myc.lineCap = 'round';
myc.beginPath();
myc.fillStyle = "#000";
myc.arc(width/2, height/2, height/2, 0, 2*Math.PI);
myc.fill();
myc.beginPath();
myc.fillStyle = "#fff";
myc.arc(width/2, height/2, height/2*0.9, 0, 2*Math.PI);
myc.fill();<span style="white-space:pre"> </span>//到这里完毕,绘制黑色圆圈
for( var i=0; i<coords.length; i++ ){<span style="white-space:pre"> </span>//绘制每个时间点
myc.beginPath();
var tmp = coords[i];
myc.moveTo(tmp[0], tmp[1]);
myc.lineTo(tmp[2], tmp[3]);
myc.strokeStyle = "#000";
myc.lineWidth = tmp[4]?width*0.02:width*0.01;<span style="white-space:pre"> </span>//当为五分,十分这些长点的时候,根据是否有额外参数,加粗
myc.stroke();
};
//绘制指针
var tmp = getPoint();<span style="white-space:pre"> </span>//获取指针数据,下面开始绘制
for( var i=0, l=tmp.length; i<l; i++ ){
myc.beginPath();
myc.moveTo(tmp[i][0],tmp[i][1]);
myc.lineTo(tmp[i][2],tmp[i][3]);
if( i == 0 ){
myc.lineWidth = width*0.03;<span style="white-space:pre"> </span>//时针,分针,秒针,分别设置不同的宽度值
}else if( i==1 ){
myc.lineWidth = width*0.02;
}else if( i==2 ){
myc.lineWidth = width*0.01;
}
myc.strokeStyle = "#000";<span style="white-space:pre"> </span>//在指针外绘制白色阴影,让看起来更有层次感
myc.shadowBlur = 4;
myc.shadowColor = "#fff";
myc.stroke();
//指针圆
if( i==2 ){<span style="white-space:pre"> </span>//这里是判断是否是秒针,秒针会绘制指针上面的圆圈
myc.beginPath();
var x = tmp[i][4];
var y = tmp[i][5];
myc.arc(x, y, width*0.03, 0 , 2*Math.PI);
myc.fillStyle = "#fff";
myc.fill();
myc.strokeStyle = "#000";
myc.stroke();
};
};
//绘制中心圆
myc.beginPath();
myc.arc(width/2, height/2, width*0.03/2, 0 ,2*Math.PI);
myc.fillStyle = "#fff";
myc.fill();
myc.beginPath();
myc.arc(width/2, height/2, width*0.018/2, 0 ,2*Math.PI);
myc.fillStyle = "#000";
myc.fill();
myc.beginPath();
myc.arc(width/2, height/2, width*0.005/2, 0 ,2*Math.PI);
myc.fillStyle = "#fff";
myc.fill();
这是绘制函数的最后部分,绘制中心点,更好看
canvas时钟制作完毕,这就是整个运行的过程,主要是算好坐标点。