html5绘制一个时钟,数字时钟html简单代码
这是数字时钟。当时觉得这是个好主意,但也没折腾。直到昨天,我同事又在网上看到这个案例,觉得很酷,就跑过来问我是怎么实现的。然后大概想了一下实现方法,有点兴趣了,就花了点时间模仿做了一个。不同的是Cenan用div来做。我用画布来实现它。在性能上用canvas会更好,因为仅仅是控制各个点的运动,用js控制dom的style属性和用js控制canvas绘制相比,在性能上肯定是有所欠缺的。
先做我做的DEMO,然后简单描述一下这样做的方法:看DEMO的时候请戳我。
这个想法很简单,就是用一个字符串保存每个数字的位置:
复制代码
XML/HTML代码将内容复制到剪贴板var numdata=[ 1111/1001/1001/1001/1111 ,//0 0001/0001/0001/0001/0001/0001/0001/0001/0001/0001/0001/0001/0001/0001/0001。//1 1111/0001/0001/1111/1000/1000/1111,//2 1111/0001/0001/1111/0001/0001/1111,//3 1010/1010/1010/1111/0010/0010/0010, //4 1111/1000/1000/1111/0001/0001/1111,//5 1111/1000/1000/1111/1001/1001/1111,//6 1111/0001/0001/0001/0001/0001/0001, //7 1111/1001/1001/1111/1001/1001/1111,//8 1111/1001/1111/0001/0001/1111,//9
XML/HTML代码将内容复制到剪贴板1111 1001 1001 1001 1001 1001 1001 1001 1001 1111,这样就清楚了。还有一种:从0到9的符号,都用字符串表示。
然后写一个粒子对象,也就是像素:
XML/HTML代码复制内容到剪贴板varP_radius=8,Gravity=9.8var particle=function(){ this . x=0;this . y=0;this . VX=0;this . vy=0;this . color=“”;this.visible=falsethis.drop=false} particle . prototype={ constructors:particle,paint:function(){//自己画CTX . fill style=this . color;CTX . begin path();ctx.arc(this.x,this.y,P_radius,0,2*Math。PI);CTX . fill();}、reset:function(x,y,color){//Reset this . x=x;this.y=ythis . VX=0;this . vy=0;this.color=colorthis.visible=truethis.drop=false},is drop:function(){//drop this . drop=true;varvx=math . random()* 20 15 this . VX=math . random()=0.5?-VX:VX;}、update:function(time){//每帧的动作if(this . drop){ this . x=this . VX * time;this . y=this . vy * time;varvy=this.vy重力*时间;if(this . y=canvas . height-P _ radius){ this . y=canvas . height-P _ radius vy=-vy * 0.7;} this.vy=vyif(this . x-P _ radius this . xcan vas . width P _ radius this . y-P _ radius this . ycan vas . height P _ radius){ this . visible=false;}}}}粒子对象的属性比较简单,比如位置、速度、可视化。方法,paint是绘制方法,reset是重置(因为需要回收粒子来提高性能),isDrop是粒子下落方法,update是更新每帧粒子的动作。在update中,当粒子移动到画布的绘图区域之外时,其可视化设置为false,并保存在粒子容器中以等待下一次调用。
写完粒子对象后,就要考虑如何根据粒子的位置来绘制粒子,同时在不需要粒子的时候,可以用自由落体的方式来动画。
先画背景(也就是没有像素的白点):
XML/HTML代码将内容复制到剪贴板functiondrawbg(){ vartx=(canvas . width-((p _ radius * 2x _ j)* 4 * 8 7 * xjg))/2;for(vari=0;i8;I){ varty=(canvas . height-((P _ radius yjg)* 6))/2;for(varj=0;jnumData[0]。长度;j ){ vartt=numData[0]。charAt(j);if(TT===/){ ty=yjg;} else { varx=tx J % 5 *(P _ radius * 2x _ J),y=tybgctx . fill style= # FFF ;bgctx . begin path();bgctx.arc(x,y,P_radius,0,2*Math。PI);bgctx . fill();} } tx=xjg 4 *(P _ radius * 2x _ J);}}先把背景画到离屏画布上,缓存起来。然后在重画每一帧的时候,就不需要逻辑计算了。直接画那个离屏画布就行了。上面的逻辑应该不难理解,就是通过两个循环,循环8个数字,然后逐点抽取每个数字。当遇到“/”时,表示换行。向绘制的ty添加换行符间隔,重置tx,然后绘制。这样,所有的点都可以画出来。效果图如下:
背景完成后,开始按照每秒绘制数字像素。主要方法是这样的:
XML/HTML代码将内容复制到剪贴板函数settime(time){ varh=time . get hours() ,m=time.getminutes() ,s=time . get seconds() ;hh=h.length===1?0 h:h;mm=m.length===1?0 m:m;ss=s.length===1?0的:s;varnowdate=h : m : s;vartx=(canvas . width-((P _ radius * 2 X _ J)* 4 * 8 7 * xjg))/2,color=“”;for(vari=0;inowdate.lengthi ){ varn=nowdate.charAt(i)==:?10:parseInt(nowdate.charAt(i)),text=numData[n];varty=(canvas . height-((P _ radius yjg)* 6))/2;开关(I){ case 0:color= # 4d CB 74 ;打破;情况2:color= # 4062 E0 ;打破;情况3:color= # d 65050 ;打破;情况5:color= # 4062 E0 ;打破;案例6:color= # 797 c17 ;打破;} for(varj=0;jtext.lengthj){ vartt=text . charat(j);if(TT===/){ ty=yjg;} else { varx=tx J % 5 *(P _ radius * 2x _ J),y=ty,pp=null,usefullp=nullparticles . foreach(function(p){ if(p . visible p . x===XP . y===y){ PPP=p;}elseif(!p . visibleusefullp===null){ usefullp=p;} });如果(pp!==nulltt=== 0 ){ PP . is drop();} else if(PP===nulltt=== 1 ){ usefullp . reset(x,y,color);} } } tx=xjg 4 *(P _ radius * 2x _ J);}}原理也不难,和上面的背景图差不多。遍历所有点,然后根据当前时间数转换的字符串判断当前点是否应该有像素。如果有像素,判断当前点是否有粒子物体。如果已经有粒子物体了,直接跳出来,不要处理。如果没有粒子对象,请在粒子容器中找到一个未使用的粒子,并将其重置到该位置。还有一种情况,就是当前点应该没有像素,但是有粒子,那么得到这个粒子,让它自由落体。
写入时间集后,您可以编写阶段更新的代码:
XML/HTML代码将内容复制到剪贴板vartimecount _ 0=0,timecount _ 1=0,particles=[];functioninitAnimate(){ for(vari=0;i200I){ varp=new particle();粒子. push(p);} time count _ 0=newDate();time count _ 1=new date();draw BG();setTime(time count _ 0)animate();} function animate(){ CTX . clear rect(0,0,canvas.width,canvas . height);ctx.drawImage(bgcanvas,0,0);vartime count _ 2=newDate();if(time count _ 1-time count _ 0=1000){ setTime(time count _ 1);时间计数_ 0=时间计数_ 1;} particles . foreach(function(p){ if(p . visible){ p . update((time count _ 2-time count _ 1)/70);p . paint();} });时间计数_ 1=时间计数_ 2;RAF(animate)}在initAnimate中初始化动画。初始化就是实例化两百个粒子对象并存储在一个粒子容器中,然后更新时间戳,缓存背景,设置当前时间,然后调用animate动画循环的主体开始动画。
animate中的逻辑也很简单。获取时间戳,如果两个时间戳的时间差大于等于1秒,则设置时间。下一步是在遍历循环中重新绘制粒子容器中的所有可视化粒子。
然后就完成了:
这个效果还有很多需要优化的地方。因为时钟和分钟动的比较少,所以可以缓存这两个,没有动作的时候直接把缓存的数据画出来就行了。这将减少舞台的每一帧的绘图API的调用量,并且肯定会提高性能。但是现在毕竟粒子不多,两三百个粒子物体就够了。如果不优化,动画依然可以流畅运行。所以楼主偷了点懒。
源代码:3359 github . com/whx axes/canvas-test/blob/GH-pages/src/fun-demo/cool clock/index . html
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。