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

Tracey_W Tracey_W     2022-09-23     801

关键词:

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;
    // 小时 为了显示效果好看、设置居中,给每个数字设置margin
     renderDigit( 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();             
            }            
        }        
    }    
}

 

canvas之星空动画

...天就来看看详细解剖下吧。实现思路首先了解下canvas中的动画原理?canvas中的动画其实是通过不断的重绘来实现动起来的效果的。通过设计小球的位置变化,达到小球不断运动的效果。同时也可以设计小球衍射,大小的变化实现... 查看详情

炫丽的倒计时效果canvas绘图与动画基础(代码片段)

前言想要在自己做的网页中,加入canvas动画效果,但是发现模板各种调整不好,觉得还是要对canvas有所了解,才可以让自己的网页变得狂拽炫酷吊炸天!一、绘制基础1<!DOCTYPEhtml>2<htmllang="en">3<head>4<metacharset="UTF-8"&... 查看详情

canvas动画之三--黑客帝国文字掉落效果(代码片段)

今天要实现的效果是黑客帝国里面的文字掉落效果,先来看一下图点击这里,查看demo其实效果也是比较好实现的,只要计算出每个文字该出现的地方,然后绘制文字就可以了。下面就来说具体的实现方法吧。首先... 查看详情

炫丽的倒计时效果canvas绘图与动画基础

digit.js1digit=[2[3//04[0,0,1,1,1,0,0],5[0,1,1,0,1,1,0],6[1,1,0,0,0,1,1],7[1,1,0,0,0,1,1],8[1,1,0,0,0,1,1],9[1,1,0,0,0,1,1],10[1,1,0,0,0,1,1],11[1,1,0,0,0,1,1],12[0,1,1,0,1,1,0],13[0,0,1,1,1,0,0]14],1 查看详情

canvas画布实现自定义时钟效果

<!doctypehtml><html><head><metacharset="utf-8"><title>标题</title><metaname="keywords"content=""><metaname="description"content=""><style> *{margin: 查看详情

打地鼠游戏之动画效果

在第一篇中,我们已经实现了单击开始后游戏的倒计时,那么下面,我们需要继续在Game这个简直对对象中进行扩展属性和方法:首先我们需要在Game中添加几组初始键值对://所有的地鼠dom元素 allMouse:[], //目前分数 nowScore:0, //目... 查看详情

canvas浅谈实现简单的自旋转下落

...理解。但是在canvas中,如果要实现一个旋转,是需要旋转画布来实现。如下图:实现代码functioncreateRect(){varanger=0,//旋转角度rectW=200,//宽度rectH=200,// 查看详情

canvas画布

...动画,游戏都可以使用canvas实现了。Canvas是一个轻量级的画布,使用Canvas进行JS编程。 Canvas基本使用<body><!--canvas画布的宽高设置需要使用属性,如果使用css会导致绘制内容变形--><canvasid="canvasId">低版本提示语,... 查看详情

canvas画布实现一个动态效果小demo(滚动圆)(代码片段)

...反弹效果。二:解题思路:明确使用的api是canvas画布。动态效果使用了定时器。首先绘制出静态结构。计算出圆移动时圆心的坐标。计算出圆碰到盒子边框反弹效果的条件。使用定时器动态实现效果。 查看详情

canvas动画之二--创建动态粒子网格动画(代码片段)

最近看到一个粒子网格动画挺炫的,自己也就做了一个,当背景挺不错的。CSDN不能上传超过2M的图片,所以就简单截了一个静态图片:可以点击这里查看动画.下面就开始说怎么实现这个效果吧:首先当然是添... 查看详情

在画布上创建线条动画(代码片段)

...线条:我如何初始设置动画位置,是否需要通过setTimeout更新?这是我到目前为止尝试的内容:varcanvas=document.getElementById("myCanvas");varctx=canvas.getContext("2d");if(canvas.getContext)varctx=canvas.getContext('2d');//drawingcodehere/*FirstRow*/ctx.fillStyle="rgb... 查看详情

怎么设置canvas动画为背景

参考技术A使用HTML5画布canvas能够快速实现简单的动画效果,基本原理如下:每隔一定时间绘制图形并且清除图形,用来模拟出一个动画过程,可以使用context.clearRect(0,0,x,y)方法来刷新需要绘制的图形首先是绘制图形的方法,如下... 查看详情

canvas画布与画布内容都缩小如何实现?

...为了解决canvas在高清屏下模糊的问题,后来经过放大canvas画布后效果得到改善(附图1);后来下载图片的时候出现了一个问题,下载的后图片的大小是画布的大小(640*1136);但是我希望下载后的图片是(320*568);请问该怎么... 查看详情

h5canvas实现圆形时间倒计时进度条(代码片段)

在项目中,我们会遇到需要显示进度条或者倒计时的功能,我们今天就来实现一下。一、效果展示实现效果要求:1.环形倒计时2.能够根据总时间和当前时间进行比例性的倒计时3.进度条环形能够有颜色渐变效果4.中间... 查看详情

h5canvas实现圆形时间倒计时进度条(代码片段)

在项目中,我们会遇到需要显示进度条或者倒计时的功能,我们今天就来实现一下。一、效果展示实现效果要求:1.环形倒计时2.能够根据总时间和当前时间进行比例性的倒计时3.进度条环形能够有颜色渐变效果4.中间... 查看详情

CreateJS不会在动画中每秒更新一次动态文本框HTML 5 Canvas

...中,我正在运行一个简单的计时器脚本,它基本上从30秒倒计时到0。我想要做的是让当前秒显示在舞台上。this.stop();//COUNTDOWNTI 查看详情

用css3和canvas实现的蜂窝动画效果

近期工作时研究了一下css3动画和js动画。主要是工作中为了增强页面的趣味性,大家都有意无意的加入了非常多动画效果。当然大部分都是css3动画效果。能够gpu加速,这会降低移动端的性能需求。今天主要说的是蜂窝效果。详... 查看详情

如何用动画填充画布形状?

】如何用动画填充画布形状?【英文标题】:HowcanIfillcanvasshapewithanimation?【发布时间】:2014-06-2101:41:00【问题描述】:我是画布新手。我有一个画布形状,想将其填充为动画。HTML<canvasid="canvas"></canvas>JSvarcanvas=document.getE... 查看详情