更新——Canvas画布动画效果之实现倒计时

Hello,大家好!

小W复活啦!继续欢乐的给大家更博,输送新知识~~

不开玩笑啦!秒进正题~~~

上次更博,小W给大家介绍了Canvas画布的基础部分,以及实现了一个由7*10点阵图显示的倒计时的基本架构。

上次的效果如下图所示,仅仅只是一个时间的静态显示而已:

今天呢,小W想实现就是,让它开始倒计时!效果先给大家看一下:

Canvas画布用于图形的绘制、动画,都是通过脚本(JavaScript)实现的。

上次更博,countdown.js代码中,已经实现了时:分:秒的基本架构,先把上次的JS代码再次梳理一下,在这个基础上,小W再进行接下来的操作:

// 全局变量  有助于后期数据的变动更改  
var WINDOW_WIDTH = 1024; 
var WINDOW_HEIGHT = 768;  // 此处需要注意宽高的比例 适当缩小放大画布的时候,尽量同时缩小放大,避免出现圆形显示为椭圆形等不对称现象
var MARGIN_LEFT = 30;
var MARGIN_TOP = 60;
var RADIUS = 8;window.onload = function(){var canvas = document.getElementById("canvas");var context = canvas.getContext("2d");canvas.width = WINDOW_WIDTH;canvas.height = WINDOW_HEIGHT;render( context );
}function render( cxt ){var hours = 12;var minute = 36;var second = 59;// 小时 为了显示效果好看、设置居中,给每个数字设置marginrenderDigit( MARGIN_LEFT , MARGIN_TOP , parseInt(hours/10) , cxt ); // 每个字水平点阵个数为直径7,半径:7*2 = 14,14+1 = 15 (1间隔)    renderDigit( MARGIN_LEFT + 15*(RADIUS+1) , MARGIN_TOP , parseInt(hours%10) , cxt );// 冒号 (4*2+1)= 9  digit.js中 10代表 :renderDigit( MARGIN_LEFT+ 30*(RADIUS+1) , MARGIN_TOP , 10 , cxt );// 分钟 renderDigit( MARGIN_LEFT+ 39*(RADIUS+1) , MARGIN_TOP , parseInt(minute/10) , cxt );renderDigit( MARGIN_LEFT+ 54*(RADIUS+1) , MARGIN_TOP , parseInt(minute%10) , cxt );renderDigit( MARGIN_LEFT+ 69*(RADIUS+1) , MARGIN_TOP , 10 , cxt );//renderDigit( MARGIN_LEFT+ 78*(RADIUS+1) , MARGIN_TOP , parseInt(second/10) , cxt );renderDigit( MARGIN_LEFT+ 93*(RADIUS+1) , MARGIN_TOP , parseInt(second%10) , cxt );    
}function renderDigit(x , y , num , cxt){     // X轴坐标、Y轴坐标、将要显示的数字、canvas上下文语境
  cxt.fillStyle = "#005588"; 

  for (var i = 0 ; i < digit[num].length ;i++) {
     
for (var j = 0 ; j < digit[num][i].length ;j++){
  
      if(digit[num][i][j] == 1){ cxt.beginPath();

        // 圆心位置公式
        cxt.arc( x+j * 2 * (RADIUS+1) + (RADIUS+1) , y+i * 2 * (RADIUS+1) + (RADIUS+1) , RADIUS , 0 , 2*Math.PI ); cxt.closePath(); cxt.fill();
       }
     }
  }
}

梳理完成之后我们可以进行下一步操作了,首先,我们需要设置一个截止时间,倒计时就是从现在开始到截止时间所剩余的时间:

//限制: 小时二位数 不超过4天
var endTime = new Date(2017,9,15,18,15,26);   // 注意!!!:data中的参数第二个表示月份,是由0-11表示的。0 - 一月;11- 十二月

  这里需要注意,我们在之前调取小时hours的位数的时候,仅仅只是设置了两位数,因而现在我们的倒计时最多到99:99:99,也就是四天。如果有读者需要实现更长时间的倒计时,需要再做些许调整,为了效果美观整洁,我们这里只设置两位数。使用JS提供的data()方式设置截止时间。

在render函数中,如何获取当前时间距离截止时间剩余时间?

  JS的data对象给我们提供了一个getTime的方法:它返回了距离1970.1.1的00:00:00的毫秒数,用这个方法减去截止日期的getTime(),这个差值就表示中间我们需要倒计时的小时、分钟和秒数,但是由于时间是一秒一秒变动的,这个动画效果需要不断的与当前时间作比较,为此我们设计一个全局的变量,来表示现在倒计时需要多少秒?

var curShowTimeSecond = 0;   // 现在倒计时需要多少毫秒,  —— > 秒

接下来,对 curShowTimeSecond 进行具体的计算:

curShowTimeSecond = getCurShowTimeSecond(); // 封装一个函数
// javascript Date 提供了 getTime 函数 以便于获取实时时间
// getCurShowTimeSecond 函数 获取当前总共的毫秒数
function getCurShowTimeSecond(){var curTime = new Date();  // 获取当前的时间是多少var ret = endTime.getTime() - curTime.getTime();  //ret 获取截止时间与当前时间相差的毫秒数ret = Math.round( ret/1000 ); // 将毫秒转换成秒return ret>=0 ? ret : 0;     // 判断 ret,倒计时结束,函数返回0.
}

现在,剩余时间的秒数已经得到了,我们接下来需要设置小时、分钟、秒数的显示:

    var hours = parseInt( curShowTimeSecond/3600 );   // 剩余时间有多少个小时var minute = parseInt( (curShowTimeSecond - hours * 3600) / 60 );     // 减去小时,剩余时间的分钟数var second = curShowTimeSecond % 60;   // 减去小时、分钟后,剩余时间还剩多少秒

到这里,在浏览器的刷新后,倒计时可以实现实时更新了。

然而我们想要实现的是让它自己更新、变化,实现倒计时,接下来我们需要引入一个实现动画的基础函数——定时器setInterval() 方法:

// 动画效果
    setInterval(function(){render( context ); // 绘制当前的画面。update(); // 根据绘制画面所需要的数据结构,对数据结构进行调整。},50  // 毫秒);

  其实,我们可以直接获取新的时间在render()里面进行绘制就可以了,但是这个最终的效果是想要实现,随着时间变化,产生彩色小球的物理变化的动画,因为为了铺垫后文,我们使用了一个update() 函数,如下图所示:

// 时间更新函数
function update(){// 注意 render 里面是绘制curShowTimeSecond var nextShowTimeSecond = getCurShowTimeSecond();  // 下一次// 下一次要显示的时间(时\分\秒分解) var nextHours = parseInt( nextShowTimeSecond/3600 );      var nextMinute = parseInt( (nextShowTimeSecond - nextHours * 3600) / 60 );  var nextSecond = nextShowTimeSecond % 60;var curtHours = parseInt( curShowTimeSecond/3600 );    var curtMinute = parseInt( (curShowTimeSecond - curtHours * 3600) / 60 );  var curtSecond = curShowTimeSecond % 60;if(nextSecond != curtSecond)   // 下一次显示的秒数不等于当前显示的秒数了,替换为新的时间curShowTimeSecond = nextShowTimeSecond;      
}

为了避免当前新图像,与之前的图像叠加,我们在render()里面引入一个新的函数:

// 为避免新一次的图像与之前的图像叠加。
// clearRect(): 对一个矩形空间内的图像进行一次刷新操作。这里,对整个屏幕进行一次操作、刷新。cxt.clearRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT);

到这里我们今天的效果已经基本实现了。

后续学习后,还会继续更新,与大家分享...希望可以多多关注!

如果有任何问题,大家可以提出来,小W同大家一起解决,有何不妥的地方也请大神多多指教,这次的博文就到这了,谢谢大家!

 附完整countdown.js代码 

var WINDOW_WIDTH = 1024;
var WINDOW_HEIGHT = 768;
var MARGIN_LEFT = 30;
var MARGIN_TOP = 60;
var RADIUS = 8;//限制: 小时二位数 不超过4天
var endTime = new Date(2017,9,15,18,15,26);   // 注意!!!:data中的参数第二个表示月份,是由0-11表示的。0 - 一月;11- 十二月
var curShowTimeSecond = 0;   // 现在倒计时需要多少毫秒
window.onload = function(){var canvas = document.getElementById("canvas");var context = canvas.getContext("2d");canvas.width = WINDOW_WIDTH;canvas.height = WINDOW_HEIGHT;curShowTimeSecond = getCurShowTimeSecond();   //curShowTimeSecond:当前总共的毫秒数// 动画效果
    setInterval(function(){render( context );update();},50  // 毫秒
    );}// javascript 的 Date 提供了 getTime 函数 以便于获取实时时间
// getCurShowTimeSecond 函数 获取当前总共的毫秒数
function getCurShowTimeSecond(){var curTime = new Date();  // 获取当前的时间是多少var ret = endTime.getTime() - curTime.getTime();  //ret 获取截止时间与当前时间相差的毫秒数ret = Math.round( ret/1000 ); // 将毫秒转换成秒return ret>=0 ? ret : 0;     // 判断 ret,倒计时结束,函数返回0.
}// 时间更新函数
function update(){var nextShowTimeSecond = getCurShowTimeSecond();// 下一次要显示的时间(时分秒分解)var nextHours = parseInt( nextShowTimeSecond/3600 );      var nextMinute = parseInt( (nextShowTimeSecond - nextHours * 3600) / 60 );  var nextSecond = nextShowTimeSecond % 60;var curtHours = parseInt( curShowTimeSecond/3600 );       // 一共需要多少个小时var curtMinute = parseInt( (curShowTimeSecond - curtHours * 3600) / 60 );  var curtSecond = curShowTimeSecond % 60;if(nextSecond != curtSecond)   curShowTimeSecond = nextShowTimeSecond;}function render( cxt ){// 为避免新一次的图像与之前的图像叠加。// clearRect(): 对一个矩形空间内的图像进行一次刷新操作。这里,对整个屏幕进行一次刷新。cxt.clearRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT);var hours = parseInt( curShowTimeSecond/3600 );       // 一共需要多少个小时var minute = parseInt( (curShowTimeSecond - hours * 3600) / 60 );  var second = curShowTimeSecond % 60;// 小时renderDigit( MARGIN_LEFT , MARGIN_TOP , parseInt(hours/10) , cxt ); // 每个字水平位置直径7,7*2 = 14半径+1 = 15     renderDigit( MARGIN_LEFT + 15*(RADIUS+1) , MARGIN_TOP , parseInt(hours%10) , cxt );// 冒号 (4*2+1)= 9  digit.js中 10代表 :renderDigit( MARGIN_LEFT+ 30*(RADIUS+1) , MARGIN_TOP , 10 , cxt );// 分钟 renderDigit( MARGIN_LEFT+ 39*(RADIUS+1) , MARGIN_TOP , parseInt(minute/10) , cxt );renderDigit( MARGIN_LEFT+ 54*(RADIUS+1) , MARGIN_TOP , parseInt(minute%10) , cxt );// 冒号 (4*2+1)= 9  digit.js中 10代表 :renderDigit( MARGIN_LEFT+ 69*(RADIUS+1) , MARGIN_TOP , 10 , cxt );//renderDigit( MARGIN_LEFT+ 78*(RADIUS+1) , MARGIN_TOP , parseInt(second/10) , cxt );renderDigit( MARGIN_LEFT+ 93*(RADIUS+1) , MARGIN_TOP , parseInt(second%10) , cxt );    
}function renderDigit(x , y , num , cxt){cxt.fillStyle = "#005588";for (var i = 0 ; i < digit[num].length ;i++) {for (var j = 0 ; j < digit[num][i].length ;j++){if(digit[num][i][j] == 1){cxt.beginPath();// 圆心位置公式cxt.arc( x+j * 2 * (RADIUS+1) + (RADIUS+1) ,  y+i * 2 * (RADIUS+1) + (RADIUS+1) , RADIUS , 0 , 2*Math.PI );cxt.closePath();                                        cxt.fill();             }            }        }    
}

 

转载于:https://www.cnblogs.com/Tracey-1023/p/7667878.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/415580.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5 微信公众号开发 获取 access_token

在使用微信公众号接口中&#xff0c;需要access_token。access_token是公众号的全局唯一凭证。可以理解为我们服务器的身份证。 总结以上说明&#xff0c;access_token需要做到以下两点&#xff1a; 1.因为access_token有2个小时的时效性&#xff0c;要有一个机制保证最长2个…

Android TextView 设置文字背景色或文字颜色,字体阴影,字体样式

//第一个字符变色String copiesStr_notic tv_notic.getText().toString().trim();SpannableString spannableString2 new SpannableString(copiesStr_notic);//0 第一行缩进像素 , SizeUtils.dp2px(15)非第一行缩进像素Paint mPaintnew Paint();float wmPaint.measureText(cop…

微信公众号 和 微信小程序 用户数据互通 通过微信开放平台的UnionID机制

很多时候&#xff0c;需要将多个公众号和小程序的用户数据打通&#xff0c;我们需要做的&#xff0c;就是将这些公众号和小程序都绑定到同一个微信开发平台上&#xff0c;那么我们就可以获取到UnionID了。其实数据就已经打通了。 UnionID机制说明&#xff1a; 如果开发者拥有…

LR 安装与破解

LoadRunner 11 安装及破解 注意事项&#xff1a; 安装前&#xff0c;把所有的杀毒软件和防火墙关闭。 若以前安装过LoadRunner,则将其卸载。 安装路径不要带中文字符。 如果系统为WIN7&#xff0c;旗舰版才能安装。 安装完毕&#xff0c;需破解。 一&#xff0e; 下载 在HP的官…

从零开始学习springBoot2

简单修改一下: 创建一个包com.kfit.test.web&#xff0c;新建类HelloController 修改 运行访问http://127.0.0.1:8080/得到相同的结果 转载于:https://www.cnblogs.com/zhengzhouyang/p/7680482.html

如何调整压力测试工具

如何调整压力测试工具 如何调整压力测试工具 您是否曾经不得不对应用程序进行压力测试&#xff0c;而最后却发现不明白结果表明什么意义?也许问题不是出在应用程序上。也许问题出在配置压力测试工具的方式上。如果您曾经经历过这种情况&#xff0c;或者正要进行压力测试&#…

未获取root手机抓包方法

没有root的android不能使用类似shark的APP抓包&#xff0c;以下两个不root抓包的方法供参考 未获取root的Android手机抓包方法1&#xff1a;连接PC开启的WIFI PC开启WIFI热点共享&#xff0c;然后手机连接到此虚拟WIFI&#xff0c;pc上使用wireshark选择对应网卡抓包。 win7以上…

栈的应用--迷宫问题

问题描述&#xff1a;给定一个迷宫&#xff0c;给定入口和出口&#xff0c;找到从入口到出口的一条路径(任何一条路径都可以)&#xff0c;迷宫为0表示可走&#xff0c;为1表示墙。用1将迷宫围起来避免边界问题。 实现思路&#xff1a;1.DFS搜索&#xff08;递归&#xff09; 2.…

常用的方法论-PARR

转载于:https://www.cnblogs.com/qjm201000/p/7687470.html

修改wireshark协议解析规则

不同的协议有不同的解码器,wireshark尝试为每个包尝试找到正确的解码器,特定的情况有可能会选择错误的解码器。 1.使用了其它协议的标准端口&#xff0c;被错误解码&#xff0c;使用udp的80端口发送数据被当作QUIC协议解析。 wireshark菜单“Analyze–>Enabled Protocols…”…