Home  >  Article  >  Web Front-end  >  Tutorial on making a digital clock with HTML5_html5 tutorial tips

Tutorial on making a digital clock with HTML5_html5 tutorial tips

WBOY
WBOYOriginal
2016-05-16 15:46:352371browse

2015511172231746.png (836×306)

It was this digital clock. I thought it was a good idea at the time, but I didn’t bother with it. Until yesterday, my colleague saw this case on the Internet. He thought it was very cool, so he came over and asked me how it was implemented. Then I thought about the implementation method and became a little interested, so I spent some time imitating it. Made one. The difference is that Cen An uses div to make it. And I did it using canvas. It will be better to use canvas for performance, because just to control the movement of each point, using js to control the style attribute of dom is definitely lacking in performance compared to using js to control canvas drawing.

Let’s take a look at the DEMO I made first, and then briefly describe the method of doing this: Please poke me to see the DEMO.

The idea of ​​doing this is very simple, which is to save the position of each number through a string:
Copy code

XML/HTML CodeCopy content to clipboard
  1. var numData = [
  2. "1111/1001/1001/1001/1001/1001/1111", //0
  3. "0001/0001/0001/0001/0001/0001/0001", //1
  4. "1111/0001/0001/1111/1000/1000/1111", //2
  5. "1111/0001/0001/1111/0001/0001/1111", //3
  6. "1010/1010/1010/1111/0010/0010/0010", //4
  7. "1111/1000/1000/1111/0001/0001/1111", //5
  8. "1111/1000/1000/1111/1001/1001/1111", //6
  9. "1111/0001/0001/0001/0001/0001/0001", //7
  10. "1111/1001/1001/1111/1001/1001/1111", //8
  11. "1111/1001/1001/1111/0001/0001/1111", //9
  12. "0000/0000/0010/0000/0010/0000/0000", //:
  13. ]

0 means no pixels, 1 means there are pixels, / is for better appearance, it is a branch. To put it simply: for example, 0 is:

 

XML/HTML CodeCopy content to clipboard
  1. 1 1 1 1
  2. 1 0 0 1
  3. 1 0 0 1
  4. 1 0 0 1
  5. 1 0 0 1
  6. 1 0 0 1
  7. 1 1 1 1

That should make it very clear. There is also a : number from 0 to 9, which is represented by a string.

Then write a particle object, which is a pixel:

XML/HTML CodeCopy content to clipboard
  1. var P_radius = 8,Gravity = 9.8;   
  2.         var Particle = function(){   
  3.             this.x = 0;   
  4.             this.y = 0;   
  5.             this.vx = 0;   
  6.             this.vy = 0;   
  7.             this.color = "";   
  8.             this.visible = false;   
  9.             this.drop = false;   
  10.         }   
  11.         Particle.prototype = {   
  12.             constructors:Particle,   
  13.             paint:function(){        //绘制自身   
  14.                 ctx.fillStyle = this.color;   
  15.                 ctx.beginPath();   
  16.                 ctx.arc(this.x,this.y,P_radius,0,2*Math.PI);   
  17.                 ctx.fill();   
  18.             },   
  19.             reset:function(x,y,color){        //重置   
  20.                 this.x = x;   
  21.                 this.y = y;   
  22.                 this.vx = 0;   
  23.                 this.vy = 0;   
  24.                 this.color = color;   
  25.                 this.visible = true;   
  26.                 this.drop = false;   
  27.             },   
  28.             isDrop:function(){        //落下   
  29.                 this.drop = true;   
  30.                 var vx = Math.random()*20 15   
  31.                 this.vx = Math.random()>=0.5?-vx : vx;   
  32.             },   
  33.             update:function(time){        //每一帧的动作   
  34.                 if(this.drop){   
  35.                     this.x  = this.vx*time;   
  36.                     this.y  = this.vy*time;   
  37.   
  38.                     var vy = this.vy Gravity*time;   
  39.   
  40.                     if(this.y>=canvas.height-P_radius){   
  41.                         this.y = canvas.height-P_radius   
  42.                         vy = -vy*0.7;   
  43.                     }   
  44.   
  45.                     this.vy = vy;   
  46.   
  47.                     if(this.x<-P_radius||this.x>canvas.width P_radius||this.y<-P_radius||this.y>canvas.height P_radius){   
  48.                         this.visible = false;   
  49.                     }   
  50.                 }   
  51.             }   
  52.         }     
  53.   

粒子对象的属性比较简单,就位置,速度,以及是否可视化。方法的话,paint是绘制方法,reset是重置(因为粒子要循环利用的,提升性能),isDrop是粒子落下方法,update就是每一帧更新粒子的动作,update中当粒子运动超出canvas的绘制区域时,就把它的可视化置为false,在粒子容器中保存起来等待下一次调用。

  写好粒子对象后,就要考虑如何让粒子按照位置画上去,同时当粒子不需要用时能够让他做自由落体的动画了。

  先画背景(也就是那没有像素的白点):

XML/HTML Code复制内容到剪贴板
  1. function drawBg(){   
  2.             var tx = (canvas.width-((P_radius*2 X_J)*4*8 7*xjg))/2;   
  3.             for(var i=0;i<8;i ){   
  4.                 var ty = (canvas.height-((P_radius yjg)*6))/2;   
  5.                 for(var j=0;j<numData[0].length;j ){   
  6.                     var tt = numData[0].charAt(j);   
  7.                     if(tt==="/"){   
  8.                         ty =yjg;   
  9.                     }else {   
  10.                         var x = tx j%5*(P_radius*2 X_J),   
  11.                             y = ty;   
  12.                         bgctx.fillStyle = "#FFF";   
  13.                         bgctx.beginPath();   
  14.                         bgctx.arc(x,y,P_radius,0,2*Math.PI);   
  15.                         bgctx.fill();   
  16.                     }   
  17.                 }   
  18.                 tx =xjg 4*(P_radius*2 X_J);   
  19.             }   
  20.         }   

First draw the background into an off-screen canvas and cache it. Then there is no need for logical calculation when redrawing each frame. Just draw the off-screen canvas directly. The above logic should not be difficult to understand. It is to loop through 8 numbers through two loops, and then draw each number point by point. When "/" is encountered, it means that a new line is required, and the drawn ty Add a newline interval, reset tx, and then draw. Just like that, all the dots can be drawn. The rendering is as follows:
2015511172757389.png (1282×350)

After the background is drawn, start drawing digital pixels according to each second of time. The main method is this:

XML/HTML CodeCopy content to clipboard
  1. function setTime(time){   
  2.             var h = time.getHours() "",   
  3.                 m = time.getMinutes() "",   
  4.                 s = time.getSeconds() "";   
  5.             hh = h.length===1?"0" h:h;   
  6.             mm = m.length===1?"0" m:m;   
  7.             ss = s.length===1?"0" s:s;   
  8.   
  9.             var nowdate = h ":" m ":" s;   
  10.             var tx = (canvas.width-((P_radius*2 X_J)*4*8 7*xjg))/2,color = "";   
  11.             for(var i=0;i<nowdate.length;i ){   
  12.                 var n = nowdate.charAt(i)===":"?10:parseInt(nowdate.charAt(i)),   
  13.                     text = numData[n];   
  14.   
  15.                 var ty = (canvas.height-((P_radius yjg)*6))/2;   
  16.   
  17.                 switch(i){   
  18.                     case 0:color = "#4DCB74";break;   
  19.                     case 2:color = "#4062E0";break;   
  20.                     case 3:color = "#D65050";break;   
  21.                     case 5:color = "#4062E0";break;   
  22.                     case 6:color = "#797C17";break;   
  23.                 }   
  24.   
  25.                 for(var j=0;j<text.length;j ){   
  26.                     var tt = text.charAt(j);   
  27.                     if(tt==="/"){   
  28.                         ty =yjg;   
  29.                     }else{   
  30.                         var x = tx j%5*(P_radius*2 X_J),   
  31.                             y = ty,   
  32.                             pp = null,   
  33.                             usefullp = null;   
  34.                         particles.forEach(function(p){   
  35.                             if(p.visible&p.x===x&p.y===y){   
  36.                                 ppp = p;   
  37.                             }else if(!p.visible&usefullp===null){   
  38.                                 usefullp = p;   
  39.                             }   
  40.                         });   
  41.                         if(pp!==null&tt==="0"){   
  42.                             pp.isDrop();   
  43.                         }else if(pp===null&tt==="1"){   
  44.                             usefullp.reset(x , y , color);   
  45.                         }   
  46.                     }   
  47.                 }   
  48.                 tx =xjg 4*(P_radius*2 X_J);   
  49.             }   
  50.         }  

  原理也不难,也是跟上面画背景差不多,遍历所有点,然后根据当前时间的数字转换成的字符串来判断,当前点是否应该有像素,如果有像素就再判断当前这个点是否已经有粒子对象在了,如果已经有粒子对象在了,就直接跳出不处理,如果没有粒子对象在,就再粒子容器中找一个没有被使用的粒子reset到这个位置。还有一种情况,就是当前这个点是不应该有像素的,但是却有粒子,那就获取这个粒子,让这个粒子进行自由落体。

  时间设置也写好了,就可以写舞台更新的代码了:

XML/HTML Code复制内容到剪贴板
  1. var timeCount_0 = 0,timeCount_1 = 0,particles = [];   
  2.         function initAnimate(){   
  3.             for(var i=0;i<200;i ){   
  4.                 var p = new Particle();   
  5.                 particles.push(p);   
  6.             }   
  7.   
  8.             timeCount_0 = new Date();   
  9.             timeCount_1 = new Date();   
  10.             drawBg();   
  11.             setTime(timeCount_0)   
  12.             animate();   
  13.         }   
  14.   
  15.         function animate(){   
  16.             ctx.clearRect(0,0,canvas.width,canvas.height);   
  17.             ctx.drawImage(bgcanvas,0,0);   
  18.   
  19.             var timeCount_2 = new Date();   
  20.   
  21.             if(timeCount_1-timeCount_0>=1000){   
  22.                 setTime(timeCount_1);   
  23.                 timeCount_0 = timeCount_1;   
  24.             }   
  25.   
  26.             particles.forEach(function(p){   
  27.                 if(p.visible){   
  28.                     p.update((timeCount_2-timeCount_1)/70);   
  29.                     p.paint();   
  30.                 }   
  31.             });
  32.  timeCount_1 = timeCount_2;
  33. RAF(animate)
  34.                                                                                  
Perform animation initialization in initAnimate. Initialization means first instantiating two hundred particle objects and putting them in a particle container to save them. Then update the timestamp, cache the background, set the current time, and then call the animate animation loop body to start the animation.

The logic in animate is also very simple. Get the timestamp. If the time difference between the two timestamps is greater than or equal to 1 second, setTime is performed. The next step is to traverse and redraw all the visualized particles in the particle container.

Then it’s done:



2015511172909169.png (1263×507)There are still many areas that can be optimized for this effect, because the clock and minutes move relatively rarely, so these two can be cached, and when there is no action, just draw the cached data directly. This can reduce the number of drawing API calls for each frame of the stage, which will definitely improve performance. However, there are not many particles now, and two to three hundred particle objects are enough. If optimization is not done, the animation can still run smoothly. So the original poster was just a little lazy.

Source code address:

https://github.com/whxaxes/canvas-test/blob/gh-pages/src/Funny-demo/coolClock/index.html

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn