搜索
首页web前端H5教程用HTML5制作数字时钟的教程_html5教程技巧

2015511172231746.png (836×306)

就是这个数字时钟,当时觉得这个创意不错,但是也没去折腾。直到昨天同事又在网上看到这个案例,他觉得很酷炫,就跑过来问我,这个是怎么实现的,然后我大概想了一下实现方法后也来了点兴趣,就花了一点时间模仿做出来了一个。不同的是,岑安用的是div来做的。而我就是用canvas来实现的。用canvas来做性能方面会更好,因为就单单操控每个点的运动,用js控制dom的style属性跟用js控制canvas绘图相比性能方面肯定是有所欠缺的。

  先上个我做的DEMO吧,然后再简述一下做这个的方法:   看DEMO请戳我 。

  做这个思路很简单,就是通过字符串保存各个数字的位置: 
复制代码

XML/HTML Code复制内容到剪贴板
  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代表没像素,1代表有像素,/是为了更好看些,就是分行嘛,简单说起来:比如0就是:

  

XML/HTML Code复制内容到剪贴板
  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     

这样就很清楚了吧。从0到9还有一个:号都用字符串表示好。

  然后就写个粒子对象,也就是像素点:

XML/HTML Code复制内容到剪贴板
  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;i8;i++){   
  4.                 var ty = (canvas.height-((P_radius+yjg)*6))/2;   
  5.                 for(var j=0;jnumData[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.         }   

  先把背景画到一个离屏canvas中缓存起来,接下来每一帧重画的时候就不需要逻辑计算了,直接把那个离屏canvas画上去就行了。上面的逻辑应该不难理解,就是通过两个循环,循环8个数字,然后再对每个数字一个点一个点进行绘制,当遇到“/”时,就说明要换行了,把绘制的ty加个换行间隔,再把tx重置,再进行绘制。就这样,点就可以都画出来了。效果图如下:
2015511172757389.png (1282×350)

背景画好了,就开始根据每一秒的时间,画数字像素吧。方法主要是这个:

XML/HTML Code复制内容到剪贴板
  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;inowdate.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;jtext.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;i200;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.         }  

  在initAnimate进行动画初始化,初始化也就是先实例化两百个粒子对象放到粒子容器中保存起来,再更新时间戳,缓存背景,设置当前时间,然后调用animate动画循环主体开始动画。

  animate中的逻辑也很简单了,获取时间戳,如果两个时间戳之间的时间差大于或等于1秒,就进行setTime。而再下面的就是对粒子容器里的所有可视化的粒子进行遍历循环重绘了。
然后就做好啦:
2015511172909169.png (1263×507)

个效果还是有很多可以优化的地方的,因为时钟和分钟都是动的比较少的,所以可以把这两个缓存起来,当没有动作的时候就直接将缓存数据画上去就行了,这样就可以减少舞台每一帧的绘图API调用量,肯定是能提高性能的。不过现在毕竟粒子不多,两三百个粒子对象也就够用了,如果不去做优化,动画也还是能很流畅的运行的。所以楼主就偷个小懒啦。

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

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
html5的div一行可以放两个吗html5的div一行可以放两个吗Apr 25, 2022 pm 05:32 PM

html5的div元素默认一行不可以放两个。div是一个块级元素,一个元素会独占一行,两个div默认无法在同一行显示;但可以通过给div元素添加“display:inline;”样式,将其转为行内元素,就可以实现多个div在同一行显示了。

html5中列表和表格的区别是什么html5中列表和表格的区别是什么Apr 28, 2022 pm 01:58 PM

html5中列表和表格的区别:1、表格主要是用于显示数据的,而列表主要是用于给数据进行布局;2、表格是使用table标签配合tr、td、th等标签进行定义的,列表是利用li标签配合ol、ul等标签进行定义的。

html5怎么让头和尾固定不动html5怎么让头和尾固定不动Apr 25, 2022 pm 02:30 PM

固定方法:1、使用header标签定义文档头部内容,并添加“position:fixed;top:0;”样式让其固定不动;2、使用footer标签定义尾部内容,并添加“position: fixed;bottom: 0;”样式让其固定不动。

html5中不支持的标签有哪些html5中不支持的标签有哪些Mar 17, 2022 pm 05:43 PM

html5中不支持的标签有:1、acronym,用于定义首字母缩写,可用abbr替代;2、basefont,可利用css样式替代;3、applet,可用object替代;4、dir,定义目录列表,可用ul替代;5、big,定义大号文本等等。

HTML5中画布标签是什么HTML5中画布标签是什么May 18, 2022 pm 04:55 PM

HTML5中画布标签是“<canvas>”。canvas标签用于图形的绘制,它只是一个矩形的图形容器,绘制图形必须通过脚本(通常是JavaScript)来完成;开发者可利用多种js方法来在canvas中绘制路径、盒、圆、字符以及添加图像等。

html5废弃了哪个列表标签html5废弃了哪个列表标签Jun 01, 2022 pm 06:32 PM

html5废弃了dir列表标签。dir标签被用来定义目录列表,一般和li标签配合使用,在dir标签对中通过li标签来设置列表项,语法“<dir><li>列表项值</li>...</dir>”。HTML5已经不支持dir,可使用ul标签取代。

Html5怎么取消td边框Html5怎么取消td边框May 18, 2022 pm 06:57 PM

3种取消方法:1、给td元素添加“border:none”无边框样式即可,语法“td{border:none}”。2、给td元素添加“border:0”样式,语法“td{border:0;}”,将td边框的宽度设置为0即可。3、给td元素添加“border:transparent”样式,语法“td{border:transparent;}”,将td边框的颜色设置为透明即可。

html5为什么只需要写doctypehtml5为什么只需要写doctypeJun 07, 2022 pm 05:15 PM

因为html5不基于SGML(标准通用置标语言),不需要对DTD进行引用,但是需要doctype来规范浏览器的行为,也即按照正常的方式来运行,因此html5只需要写doctype即可。“!DOCTYPE”是一种标准通用标记语言的文档类型声明,用于告诉浏览器编写页面所用的标记的版本。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
2 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
2 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。