上班发呆的时候。看到那个时钟在转。于是就想着,我也做个时钟出来吧。这个东西经常看到,但是没有自己亲自做过。那就动手试试看。看看到底难不难。
效果
先直接上效果图。只做出了功能。样子一般般
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<canvas id="myCanvas" width="200" height="200" style="border:1px solid #000000;"></canvas>
<script>
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
window.onload = function(){
setInterval(function(){
//把画布画成白色
ctx.fillStyle="#fff";
ctx.beginPath();
ctx.fillRect(0,0,c.width,c.height);
var date = new Date();
//时针
var hours = date.getHours();
hours = hours % 12;
draw_line(50,hours*5,100,100);
//分针
var minute = date.getMinutes();
draw_line(60,minute,100,100);
//秒针
var second = date.getSeconds();
draw_line(80,second,100,100);
},1000)
}
/**
* 画线
* @param int line_length 线条的长度
* @param int miao 指向几秒
* @return {[type]} [description]
*/
function draw_line(line_length,miao,x0,y0){
//度数
/*
因为钟表的开始是在坐标系的正90度位置开始。所有使用90-开始计算
*/
var du = 90 - (6 * miao);
//求y坐标
/*
因为Y的坐标方向和数学里面的坐标方向相反。所以这里Y轴需要用减法
*/
var y = y0 - Math.sin(2 * Math.PI / 360 * du) * line_length;
//求x坐标
var x = x0 + Math.cos(2 * Math.PI / 360 * du) * line_length;
//定义一个
ctx.moveTo(x0,y0);
ctx.lineTo(x,y);
ctx.stroke();
}
</script>
理解求x,y的值
线段c是我们钟表的指针。是一个已知的数。还有一个已知数我们可以知道。那就是∠A的角度。我们可以通过360÷60就知道每一秒之间的相隔的度数。得到的答案就是6°
有了以上的两个已知数之后。我们再来看看三角形的三角函数。
我们要求的就是a边和b边。通过上面的公式可以看到sinA=a/c
。通过这个公式。可以看到我们已经有两个已知数了。还差a我们不知道。刚好我们要求的也就是a。
那么怎么求出a的长度啦?
1
2
3
4
5
6
设 : 假设我们现在的∠A是30度。c的长度是6厘米
∵ sinA = a/c
∴ sin30 = a/6
两边都乘6
∴ a = sin30 * 6
∴ a = 3
cos
同理
所以得出结论
1
2
3
4
5
a = sin∠A * c
b = cos∠A * c
也就是说
x = cos∠A * c
y = sin∠A * c
将每一条线画出来
上面的准备工作我们都做完了。已经知道计算公式怎么算。怎么得到结果。现在就是把60条线画出来看看效果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<canvas id="myCanvas" width="500" height="500" style="border:1px solid #000000;">
</canvas>
<script>
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
for(var i=1;i<61;i++){
//角度
var du = 6*i;
//线条的长度
var line_length = 200;
//求Y坐标
var y = 250 - Math.sin(2 * Math.PI / 360 * du) * line_length;
//求x坐标
var x = 250 + Math.cos(2 * Math.PI / 360 * du) * line_length;
ctx.moveTo(250,250);
ctx.lineTo(x,y);
ctx.stroke();
}
</script>
可以得到下面这样的结果
现在已经离成功不远了。因为我们已经画出60条线了。也就是说。我们的算法没错。理解也没错。
写一个定时执行的方法
现在。我们可以写一个方法。再用定时执行的办法。每一秒调用一次。生成一条线。就可以看到每一秒的效果了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<canvas id="myCanvas" width="500" height="500" style="border:1px solid #000000;">
</canvas>
<script>
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
/**
* 定时执行的方法
* @param int miao 当前为第几秒
* @return {[type]} [description]
*/
function timer(miao){
//角度
var du = 6*miao;
//线条的长度
var line_length = 200;
//求Y坐标
var y = 250 - Math.sin(2 * Math.PI / 360 * du) * line_length;
//求x坐标
var x = 250 + Math.cos(2 * Math.PI / 360 * du) * line_length;
ctx.moveTo(250,250);
ctx.lineTo(x,y);
ctx.stroke();
}
window.onload = function(){
setInterval(function(){
var date = new Date();
var second = date.getSeconds();
timer(second);
})
}
</script>
结果就变成了这个样子。虽然接近我们想要的效果了。但是发现有两个问题。
- 指针是逆时针旋转的
- 每新的一秒,之前画的线没有删除,而还在继续新增线条
解决方法如下
- 因为圆的角度就是往逆时针方向增大的。而且时钟的指针是在圆的正90度开始的。所以。就需要将角度修改一下。改成
90 - (6 * miao)
这样就解决了问题 - 因为canvas的原因。在画一条新的线之前。需要把原来的界面都搽除掉。所以我使用了。
1 2 3 4
//把画布画成白色 ctx.fillStyle="#fff"; ctx.beginPath(); ctx.fillRect(0,0,c.width,c.height);
最后修改成了最上面看到的代码那样正确的执行
其他补充
- 数学里面的坐标系 X轴是向右增加的、Y轴是向上增加的。但是在html的规则里面。Y轴的方向是和正常的坐标系正好相反的。所以我们使用减法来改变坐标的方向。
Math.sin(X)
其中的X是弧度。不是角度。所以需要将角度转换为弧度2 * Math.PI / 360 * 角度
或者Math.PI / 180 * 角度