先看下显示结果:
参考:
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>