就是这个数字时钟,当时觉得这个创意不错,但是也没去折腾。直到昨天同事又在网上看到这个案例,他觉得很酷炫,就跑过来问我,这个是怎么实现的,然后我大概想了一下实现方法后也来了点兴趣,就花了一点时间模仿做出来了一个。不同的是,岑安用的是div来做的。而我就是用canvas来实现的。用canvas来做性能方面会更好,因为就单单操控每个点的运动,用js控制dom的style属性跟用js控制canvas绘图相比性能方面肯定是有所欠缺的。
先上个我做的DEMO吧,然后再简述一下做这个的方法: 看DEMO请戳我 。
做这个思路很简单,就是通过字符串保存各个数字的位置:
复制代码
- var numData = [
- "1111/1001/1001/1001/1001/1001/1111", //0
- "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/1001/1111/0001/0001/1111", //9
- "0000/0000/0010/0000/0010/0000/0000", //:
- ]
0代表没像素,1代表有像素,/是为了更好看些,就是分行嘛,简单说起来:比如0就是:
- 1 1 1 1
- 1 0 0 1
- 1 0 0 1
- 1 0 0 1
- 1 0 0 1
- 1 0 0 1
- 1 1 1 1
这样就很清楚了吧。从0到9还有一个:号都用字符串表示好。
然后就写个粒子对象,也就是像素点:
- var P_radius = 8,Gravity = 9.8;
- var Particle = function(){
- this.x = 0;
- this.y = 0;
- this.vx = 0;
- this.vy = 0;
- this.color = "";
- this.visible = false;
- this.drop = false;
- }
- Particle.prototype = {
- constructors:Particle,
- paint:function(){ //绘制自身
- ctx.fillStyle = this.color;
- ctx.beginPath();
- ctx.arc(this.x,this.y,P_radius,0,2*Math.PI);
- ctx.fill();
- },
- reset:function(x,y,color){ //重置
- this.x = x;
- this.y = y;
- this.vx = 0;
- this.vy = 0;
- this.color = color;
- this.visible = true;
- this.drop = false;
- },
- isDrop:function(){ //落下
- this.drop = true;
- var vx = 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;
- var vy = this.vy+Gravity*time;
- if(this.y>=canvas.height-P_radius){
- this.y = canvas.height-P_radius
- vy = -vy*0.7;
- }
- this.vy = vy;
- if(this.x-P_radius||this.x>canvas.width+P_radius||this.y-P_radius||this.y>canvas.height+P_radius){
- this.visible = false;
- }
- }
- }
- }
粒子对象的属性比较简单,就位置,速度,以及是否可视化。方法的话,paint是绘制方法,reset是重置(因为粒子要循环利用的,提升性能),isDrop是粒子落下方法,update就是每一帧更新粒子的动作,update中当粒子运动超出canvas的绘制区域时,就把它的可视化置为false,在粒子容器中保存起来等待下一次调用。
写好粒子对象后,就要考虑如何让粒子按照位置画上去,同时当粒子不需要用时能够让他做自由落体的动画了。
先画背景(也就是那没有像素的白点):
- function drawBg(){
- var tx = (canvas.width-((P_radius*2+X_J)*4*8+7*xjg))/2;
- for(var i=0;i8;i++){
- var ty = (canvas.height-((P_radius+yjg)*6))/2;
- for(var j=0;jnumData[0].length;j++){
- var tt = numData[0].charAt(j);
- if(tt==="/"){
- ty+=yjg;
- }else {
- var x = tx+j%5*(P_radius*2+X_J),
- y = ty;
- bgctx.fillStyle = "#FFF";
- bgctx.beginPath();
- bgctx.arc(x,y,P_radius,0,2*Math.PI);
- bgctx.fill();
- }
- }
- tx+=xjg+4*(P_radius*2+X_J);
- }
- }
先把背景画到一个离屏canvas中缓存起来,接下来每一帧重画的时候就不需要逻辑计算了,直接把那个离屏canvas画上去就行了。上面的逻辑应该不难理解,就是通过两个循环,循环8个数字,然后再对每个数字一个点一个点进行绘制,当遇到“/”时,就说明要换行了,把绘制的ty加个换行间隔,再把tx重置,再进行绘制。就这样,点就可以都画出来了。效果图如下:
背景画好了,就开始根据每一秒的时间,画数字像素吧。方法主要是这个:
- function setTime(time){
- var h = time.getHours()+"",
- m = time.getMinutes()+"",
- s = time.getSeconds()+"";
- hh = h.length===1?"0"+h:h;
- mm = m.length===1?"0"+m:m;
- ss = s.length===1?"0"+s:s;
- var nowdate = h+":"+m+":"+s;
- var tx = (canvas.width-((P_radius*2+X_J)*4*8+7*xjg))/2,color = "";
- for(var i=0;inowdate.length;i++){
- var n = nowdate.charAt(i)===":"?10:parseInt(nowdate.charAt(i)),
- text = numData[n];
- var ty = (canvas.height-((P_radius+yjg)*6))/2;
- switch(i){
- case 0:color = "#4DCB74";break;
- case 2:color = "#4062E0";break;
- case 3:color = "#D65050";break;
- case 5:color = "#4062E0";break;
- case 6:color = "#797C17";break;
- }
- for(var j=0;jtext.length;j++){
- var tt = text.charAt(j);
- if(tt==="/"){
- ty+=yjg;
- }else{
- var x = tx+j%5*(P_radius*2+X_J),
- y = ty,
- pp = null,
- usefullp = null;
- particles.forEach(function(p){
- if(p.visible&p.x===x&p.y===y){
- ppp = p;
- }else if(!p.visible&usefullp===null){
- usefullp = p;
- }
- });
- if(pp!==null&tt==="0"){
- pp.isDrop();
- }else if(pp===null&tt==="1"){
- usefullp.reset(x , y , color);
- }
- }
- }
- tx+=xjg+4*(P_radius*2+X_J);
- }
- }
原理也不难,也是跟上面画背景差不多,遍历所有点,然后根据当前时间的数字转换成的字符串来判断,当前点是否应该有像素,如果有像素就再判断当前这个点是否已经有粒子对象在了,如果已经有粒子对象在了,就直接跳出不处理,如果没有粒子对象在,就再粒子容器中找一个没有被使用的粒子reset到这个位置。还有一种情况,就是当前这个点是不应该有像素的,但是却有粒子,那就获取这个粒子,让这个粒子进行自由落体。
时间设置也写好了,就可以写舞台更新的代码了:
- var timeCount_0 = 0,timeCount_1 = 0,particles = [];
- function initAnimate(){
- for(var i=0;i200;i++){
- var p = new Particle();
- particles.push(p);
- }
- timeCount_0 = new Date();
- timeCount_1 = new Date();
- drawBg();
- setTime(timeCount_0)
- animate();
- }
- function animate(){
- ctx.clearRect(0,0,canvas.width,canvas.height);
- ctx.drawImage(bgcanvas,0,0);
- var timeCount_2 = new Date();
- if(timeCount_1-timeCount_0>=1000){
- setTime(timeCount_1);
- timeCount_0 = timeCount_1;
- }
- particles.forEach(function(p){
- if(p.visible){
- p.update((timeCount_2-timeCount_1)/70);
- p.paint();
- }
- });
- timeCount_1 = timeCount_2;
- RAF(animate)
- }
在initAnimate进行动画初始化,初始化也就是先实例化两百个粒子对象放到粒子容器中保存起来,再更新时间戳,缓存背景,设置当前时间,然后调用animate动画循环主体开始动画。
animate中的逻辑也很简单了,获取时间戳,如果两个时间戳之间的时间差大于或等于1秒,就进行setTime。而再下面的就是对粒子容器里的所有可视化的粒子进行遍历循环重绘了。
然后就做好啦:
个效果还是有很多可以优化的地方的,因为时钟和分钟都是动的比较少的,所以可以把这两个缓存起来,当没有动作的时候就直接将缓存数据画上去就行了,这样就可以减少舞台每一帧的绘图API调用量,肯定是能提高性能的。不过现在毕竟粒子不多,两三百个粒子对象也就够用了,如果不去做优化,动画也还是能很流畅的运行的。所以楼主就偷个小懒啦。
源码地址:https://github.com/whxaxes/canvas-test/blob/gh-pages/src/Funny-demo/coolClock/index.html

HTML中的H5标签是第五级标题,用于标记较小的标题或子标题。1)H5标签帮助细化内容层次,提升可读性和SEO。2)结合CSS可定制样式,增强视觉效果。3)合理使用H5标签,避免滥用,确保内容结构逻辑性。

HTML5构建网站的方法包括:1.使用语义化标签定义网页结构,如、、等;2.嵌入多媒体内容,使用和标签;3.应用表单验证和本地存储等高级功能。通过这些步骤,你可以创建一个结构清晰、功能丰富的现代网页。

通过合理的H5代码结构可以让页面在众多内容中脱颖而出。1)使用语义化标签如、、等组织内容,使结构清晰。2)通过CSS布局如Flexbox或Grid控制页面在不同设备上的呈现效果。3)实现响应式设计,确保页面在不同屏幕尺寸上自适应。

HTML5(H5)与旧版本HTML的主要区别包括:1)H5引入了语义化标签,2)支持多媒体内容,3)提供离线存储功能。H5通过新标签和API增强了网页的功能和表现力,如和标签,提高了用户体验和SEO效果,但需注意兼容性问题。

H5和HTML5的区别在于:1)HTML5是网页标准,定义结构和内容;2)H5是基于HTML5的移动网页应用,适用于快速开发和营销。

HTML5的核心特性包括语义化标签、多媒体支持、表单增强和离线存储与本地存储。1.语义化标签如、等提高了代码可读性和SEO效果。2.多媒体支持通过和标签简化了嵌入媒体内容的过程。3.表单增强引入了新的输入类型和验证属性,简化了表单开发。4.离线存储和本地存储通过ApplicationCache和localStorage等提高了网页性能和用户体验。

html5isamajorrevisionofthehtmlStandardThatRevolutionsWebDevelopmentBybyIntroDucingNewSemanticeLementSemelementsandAndCapabilities.1)itenhancesCodereAdabilityAndSeowitability andSeowithelientsLike,and.2)

H5的高级技巧包括:1.利用进行复杂图形绘制,2.使用WebWorkers提升性能,3.通过WebStorage增强用户体验,4.实现响应式设计,5.利用WebRTC实现实时通信,6.进行性能优化和最佳实践。这些技巧帮助开发者构建更动态、互动和高效的Web应用。


热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

Atom编辑器mac版下载
最流行的的开源编辑器

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

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

SublimeText3汉化版
中文版,非常好用

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