Tutorial on making digital clock with HTML5

Time:2021-12-28

2015511172231746.png (836×306)

This is the digital clock. I thought it was a good idea at that time, but I didn’t bother. Until yesterday, my colleague saw this case on the Internet. He thought it was cool, so he ran over to me and asked me how to realize it. Then I thought about the implementation method and became a little interested, so I took a little time to imitate and make one. The difference is that Cen an uses div to do it. And I use canvas to realize it. Using canvas to do performance is better, because just controlling the motion of each point, using JS to control the style attribute of DOM is certainly lacking in performance compared with using JS to control canvas drawing.

Let’s start with my demo, and then briefly describe the method of doing this: look at demo, please poke me.

The idea is very simple, that is to save the position of each number through the string:
Copy code

XML/HTML CodeCopy contents 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 pixels, / for a better look, it’s a branch. To put it simply: for example, 0 means:

  

XML/HTML CodeCopy contents to clipboard
  1.         1  1  1  1   
  2.   
  3.   1  0  0  1   
  4.   
  5.   1  0  0  1   
  6.   
  7.   1  0  0  1   
  8.   
  9.   1  0  0  1   
  10.   
  11.   1  0  0  1   
  12.   
  13.   1  1  1  1     

That’s clear. From 0 to 9, there is another: signs are represented by strings.

Then write a particle object, that is, pixels:

XML/HTML CodeCopy contents 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() {/ / paint itself
  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) {/ / reset
  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() {/ / drop
  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) {/ / action of each frame
  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.   

The properties of Particle objects are relatively simple, such as position, speed, and whether they are visualized. Method, paint is the painting method, reset is the reset (because particles need to be recycled to improve performance), isdrop is the particle falling method, and update is the action of updating particles every frame. In update, when the particle moves beyond the canvas painting area, its visualization is set to false and saved in the particle container for the next call.

After writing the particle object, we should consider how to draw the particle according to its position. At the same time, when the particle doesn’t need to be used, we can let it animate the free falling body.

Draw the background first (that is, the white dot without pixels):

XML/HTML CodeCopy contents to clipboard
  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, when each frame is redrawn, there is no need for logical calculation. Just draw the off screen canvas directly. The above logic should not be difficult to understand, that is, through two cycles, cycle 8 numbers, and then draw each number point by point. When “/” is encountered, it means that line breaking is required. Add a line breaking interval to the drawn ty, reset TX, and then draw. In this way, the dots can be drawn. The renderings are as follows:
2015511172757389.png (1282×350)

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

XML/HTML CodeCopy contents 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.         }  

The principle is not difficult. It is similar to the background drawn above. Traverse all points, and then judge whether there should be pixels at the current point according to the string converted from the number of the current time. If there are pixels, judge whether there is a particle object at the current point. If there is a particle object, jump out directly and do not process it. If there is no particle object, Find an unused particle in the particle container and reset it to this location. In another case, there should be no pixels at the current point, but there are particles. Then get the particle and let the particle fall freely.

After the time setting is also written, you can write the code for stage update:

XML/HTML CodeCopy contents to clipboard
  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.   
  33.             timeCount_1 = timeCount_2;   
  34.   
  35.             RAF(animate)   
  36.         }  

Initializing animation in initAnimate, initialization is to instantiate two hundred Particle objects into the particle container, then update the timestamp, cache the background, set the current time, and then invoke the animate animation loop body to start animation.

The logic in animate is also very simple. Obtain the timestamp. If the time difference between the two timestamps is greater than or equal to 1 second, setTime will be performed. The following is the traversal cycle redrawing of all visual particles in the particle container.
Then it’s done:
2015511172909169.png (1263×507)

There are still many places to optimize this effect. Because the clock and minutes move less, you can cache these two effects. When there is no action, just draw the cached data directly. In this way, you can reduce the amount of drawing API calls for each frame of the stage, which will certainly improve the performance. But now, after all, there are not many particles, and two or three hundred Particle objects are enough. If you don’t optimize, the animation can still run smoothly. So the landlord stole a little lazy.

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