canvas 钟表

上周开始利用闲暇时间看html5 canvas技术。觉得非常好玩。就利用 canvas 做了一个简陋的钟表。源码非常简单,但是在制作的过程中,进入的误区却不少,浪费了很多时间。先上源码,然后在说说我走的岔路。

源码是基于 require.js 去写的,可以去 官网 了解 require.js 的详细资料。

 1 define(function(){

 2     function T_clock(options){

 3         this.container = options.container || document.body;

 4         if(!document.createElement('canvas').getContext){

 5             alert('当前浏览器不支持canvas!');

 6             return;

 7         }

 8         this.init();

 9     };

10     var cfg = {

11         bg:'#ffaa77',

12         bg_rbga:'rgba(255,170,119,1)',

13         outCircleLen:99,

14         innerCircleLen:94,

15         minLen:65,

16         secLen:75,

17         hourLen:55,

18         ctx:undefined

19     };

20     T_clock.prototype.init = function(){

21         var cv = document.createElement('canvas');

22         this.container.appendChild(cv);

23         cv.height = 600;

24         cv.width = 800;

25         cv.style.backgroundColor = cfg.bg;

26         if(cv.getContext){

27             cfg.ctx = cv.getContext('2d');

28         }

29         setInterval(function(){

30             cfg.ctx.clearRect(0,0,800,600);

31             cfg.ctx.beginPath();

32             cfg.ctx.lineWidth = 1;

33             cfg.ctx.arc(100,100,cfg.outCircleLen,0,2*Math.PI,false);

34             cfg.ctx.moveTo(100 + cfg.innerCircleLen,100);

35             cfg.ctx.arc(100,100,94,0,2*Math.PI,false);

36 

37             cfg.ctx.font = 'bold 14px 宋体';

38             cfg.ctx.textAlign = 'center';

39             cfg.ctx.textBaseline = 'middle';

40             var numR = 76,x,y,arc;

41             for(var i=1,arc=-Math.PI/3;i<13;i++,arc+= Math.PI/6){

42                 x = 100 + numR * Math.cos(arc);

43                 y = 100 + numR * Math.sin(arc);

44                 cfg.ctx.fillText(i,x,y);

45             }

46             for(i=0,arc=-Math.PI/2; i<60; i++,arc+=Math.PI/30){

47                 x = 100 + 94 * Math.cos(arc);

48                 y = 100 + 94 * Math.sin(arc);

49                 cfg.ctx.moveTo(x,y);

50                 if(i % 5 == 0){

51                     x = 100 + (94 - 10) * Math.cos(arc);

52                     y = 100 + (94 - 10) * Math.sin(arc);

53                 }

54                 else{

55                     x = 100 + (94 - 5) * Math.cos(arc);

56                     y = 100 + (94 - 5) * Math.sin(arc);

57                 }

58                 cfg.ctx.lineTo(x,y);

59             }

60             cfg.ctx.closePath();

61             cfg.ctx.stroke();

62 

63             var d = new Date();

64             var sec = d.getSeconds();

65             var min = d.getMinutes();

66             var hour = d.getHours();

67             var sec_angle = - Math.PI * sec / 30 + Math.PI;

68 

69             cfg.ctx.beginPath();

70             cfg.ctx.strokeStyle = '#F00';

71             cfg.ctx.lineWidth = 1;

72             cfg.ctx.moveTo(100,100);

73             cfg.ctx.lineTo(100 + cfg.secLen * Math.sin(sec_angle),100 + cfg.secLen * Math.cos(sec_angle));

74             cfg.ctx.closePath();

75             cfg.ctx.stroke();

76 

77             cfg.ctx.beginPath();

78             cfg.ctx.strokeStyle = '#555';

79             cfg.ctx.lineWidth = 2;

80             cfg.ctx.moveTo(100,100);

81             var min_angle = - Math.PI * min / 30 + Math.PI - Math.PI * sec / 1800;

82             cfg.ctx.lineTo(100 + cfg.minLen * Math.sin(min_angle),100 + cfg.minLen * Math.cos(min_angle));

83             cfg.ctx.closePath();

84             cfg.ctx.stroke();

85 

86             cfg.ctx.beginPath();

87             cfg.ctx.strokeStyle = '#000';

88             cfg.ctx.lineWidth = 2;

89             cfg.ctx.moveTo(100,100);

90             var hour_angle = - Math.PI * hour / 6 + Math.PI - Math.PI * min / 360;

91             cfg.ctx.lineTo(100 + cfg.hourLen * Math.sin(hour_angle),100 + cfg.hourLen * Math.cos(hour_angle));

92             cfg.ctx.closePath();

93             cfg.ctx.stroke();

94         },1000);

95 };

96 

97 return T_clock;

98 })
钟表模块
1     require(['../../js/require/config.js'],function(cfg){

2         require(['h5/L_canvas'],function(Canvas){

3             new Canvas({});

4         });

5     })
引用钟表模块

上效果图;canvas 钟表

误区一:错误的理解 canvas 中的每一个图(画的每一个元素)都是一个单独的对象,可以自己销毁(擦除)自己。其实不是这样的,canvas 的 context 对象只提供了一个 clearRect 方法去清空指定区域的内容。

误区二:在一个钟表里,只有指针是动的,钟表的圆盘及数字是不动的。于是我就想在做指针动画的时候,不清除钟表的圆盘和数字,只是清除指针重画指针来实现这样的效果。期间我试了很多办法都不行。最典型的就是用了 canvas 的这个属性 globalCompositeOperation, 通过用背景色重画动画的上一个动作,用于擦除上一个动画,效果非常的莫名其妙,推测应该是 Math 对象的一些运算结果都不是精确值导致的。最后我只能在每次心跳时,清空画布重画钟表的圆盘和数字来实现动画效果;

误区三:每画一个元素,如果样式和下一个原色的样式不一样,都要单独设置元素的样式,并且要嵌在context.beginPah,context.closePath()内部,每调用closePath方法,都要调用Stroke或者fill方法把元素画出来。否则画布不会显示的。参看上传的第一块代码。

你可能感兴趣的:(canvas)