制作一个倒计时的动画
我们来看这个动画,在时间变化的同时,会有小球动画从原时间上炸开,落到地上。因此我们主要的工作首先是要显示出由点构成的时间,其次需要每秒变化时间,最后就是小球的动画了。先来看一下效果图:
这是一个简单的1个小时倒计时的动画,接下来我们来看如何制作这段代码:
1. 时间点阵
时间点阵的显示可以通过二维数组点阵来显示,这里我们建立一个digit.js的文件专门用于时间点阵,代码如下:
//0-9为:10行7列(10*7),而冒号:(10*4)
digit =
[
[
[0,0,1,1,1,0,0],
[0,1,1,0,1,1,0],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,0,1,1,0],
[0,0,1,1,1,0,0]
],//0
[
[0,0,0,1,1,0,0],
[0,1,1,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[1,1,1,1,1,1,1]
],//1
[
[0,1,1,1,1,1,0],
[1,1,0,0,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,1,1,0],
[0,0,0,1,1,0,0],
[0,0,1,1,0,0,0],
[0,1,1,0,0,0,0],
[1,1,0,0,0,0,0],
[1,1,0,0,0,1,1],
[1,1,1,1,1,1,1]
],//2
[
[1,1,1,1,1,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,1,1,0],
[0,0,0,1,1,0,0],
[0,0,1,1,1,0,0],
[0,0,0,0,1,1,0],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,1,1,1,0]
],//3
[
[0,0,0,0,1,1,0],
[0,0,0,1,1,1,0],
[0,0,1,1,1,1,0],
[0,1,1,0,1,1,0],
[1,1,0,0,1,1,0],
[1,1,1,1,1,1,1],
[0,0,0,0,1,1,0],
[0,0,0,0,1,1,0],
[0,0,0,0,1,1,0],
[0,0,0,1,1,1,1]
],//4
[
[1,1,1,1,1,1,1],
[1,1,0,0,0,0,0],
[1,1,0,0,0,0,0],
[1,1,1,1,1,1,0],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,1,1,1,0]
],//5
[
[0,0,0,0,1,1,0],
[0,0,1,1,0,0,0],
[0,1,1,0,0,0,0],
[1,1,0,0,0,0,0],
[1,1,0,1,1,1,0],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,1,1,1,0]
],//6
[
[1,1,1,1,1,1,1],
[1,1,0,0,0,1,1],
[0,0,0,0,1,1,0],
[0,0,0,0,1,1,0],
[0,0,0,1,1,0,0],
[0,0,0,1,1,0,0],
[0,0,1,1,0,0,0],
[0,0,1,1,0,0,0],
[0,0,1,1,0,0,0],
[0,0,1,1,0,0,0]
],//7
[
[0,1,1,1,1,1,0],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,1,1,1,0],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,1,1,1,0]
],//8
[
[0,1,1,1,1,1,0],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[1,1,0,0,0,1,1],
[0,1,1,1,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,0,1,1],
[0,0,0,0,1,1,0],
[0,0,0,1,1,0,0],
[0,1,1,0,0,0,0]
],//9
[
[0,0,0,0],
[0,0,0,0],
[0,1,1,0],
[0,1,1,0],
[0,0,0,0],
[0,0,0,0],
[0,1,1,0],
[0,1,1,0],
[0,0,0,0],
[0,0,0,0]
]//:
];
这个点阵包含了0-9的数字以及一个冒号,我们在显示时间的时候只需要调用点阵相对的数字即可。
2.时间动画
我们如何能制作时间这个动画呢?要制作倒计时,首先需要知道当前时间与规定时间的差值,因此,我们为此封装一个函数getCurrentShowTimeSeconds()
//获取当前时间与规定时间之差,返回值为秒
function getCurrentShowTimeSeconds(){
var curTime = new Date()
var ret = endTime.getTime()-curTime.getTime()//此处获得为毫秒数
ret = Math.round(ret/1000)//转化为秒
return ret>=0?ret:0;
}
在这个函数中,首先我们通过js的date()函数与getTime()函数求出规定时间与当前时间的差值(单位为毫秒),然后换算为秒数,如果这个秒数大于0,则返回秒数,如果小于0 ,即当前时间已经超过了规定时间,那么返回0;
找到时间差值后,我们需要绘制出当前的时间,首先,我们需要想到,如何绘制单个数字,在这里我们建立了一个renderDigit(x,y,num,cxt)函数:
function renderDigit(x,y,num,cxt){
cxt.fillStyle = '#e89abe';
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();
}
}
}
}
renderDigit(x,y,num,cxt)函数 主要是为了绘制每个具体的数字,其中x,y是绘制出的数字的坐标,num表示需要绘制的数字是多少,在renderDigit函数中,引入digit.js并遍历所需要绘制的数字的那个数组,完整绘制出想要的数字。
当我们可以绘制每个数字后,就需要绘制出需要显示的时间的所有数字,我们将这个功能封装在render函数中:
//绘制时间
var hours = parseInt(curShowTimeSeconds/3600);
var minutes = parseInt(curShowTimeSeconds-hours*3600)/60;
var seconds = curShowTimeSeconds%60;
renderDigit(MARGIN_LEFT,MARGIN_TOP,parseInt(hours/10),cxt);
renderDigit(MARGIN_LEFT+15*(RADIUS+1), MARGIN_TOP,parseInt(hours%10),cxt);
renderDigit(MARGIN_LEFT+30*(RADIUS+1),MARGIN_TOP,10,cxt);
renderDigit(MARGIN_LEFT+39*(RADIUS+1),MARGIN_TOP,parseInt(minutes/10),cxt);
renderDigit(MARGIN_LEFT+54*(RADIUS+1), MARGIN_TOP,parseInt(minutes%10),cxt);
renderDigit(MARGIN_LEFT+69*(RADIUS+1),MARGIN_TOP,10,cxt);
renderDigit(MARGIN_LEFT+78*(RADIUS+1),MARGIN_TOP,parseInt(seconds/10),cxt);
renderDigit(MARGIN_LEFT+93*(RADIUS+1), MARGIN_TOP,parseInt(seconds%10),cxt);
其中,curShowTimeSeconds为我们最初设定的一个变量,初始值为0:
var curShowTimeSeconds = 0//表示现在距离倒计时需要多少秒
curShowTimeSeconds = getCurrentShowTimeSeconds();
通过换算,就可以获得所需要的时,分,秒的具体数值,然后我们就需要开始绘制时间:
在renderDigit函数中,x为绘制的左边距,y为绘制的右边距,num为数字
其中x如何获得是一个难点:
我们需要观察我们的digit.js中的二维数组,通过观察,可以发现0-9的数字是10*7的数组,而冒号是10*4的数组,因此每个数字的宽度应该是14*R,R为绘制出的点阵中每个点的半径,我们可以通过画格子的方式来绘制点
(图片转自慕课网liuyubobobo讲师课程炫丽的倒计时效果canvas绘图与动画基础)
这样我们就可以画出每个数字了
接下来,我们需要将时间动起来,我们将这个功能写在一个update()的函数中
var nextShowTimeSeconds = getCurrentShowTimeSeconds();
var nextHours = parseInt(nextShowTimeSeconds/3600);
var nextMinutes = parseInt(nextShowTimeSeconds-nextHours*3600)/60;
var nextSeconds = nextShowTimeSeconds%60;
var curHours = parseInt(curShowTimeSeconds/3600);
var curMinutes = parseInt(curShowTimeSeconds-curHours*3600)/60;
var curSeconds = curShowTimeSeconds%60;
if (nextSeconds != curSeconds) {
curShowTimeSeconds = nextShowTimeSeconds
}
建立一个新的变量nextShowTimeSeconds,用于存储下一次调用函数的时间,计算下一次的时间 与本次是否相同,如果相同,则不变,不同,则用新秒数替换原来的秒数,重新绘制时间
3.最后,我们需要添加小球的动画
首先,依旧是要绘制小球,绘制的功能我们都放在render函数中,我们首先设置一个balls[]数组,数组中存放着所有的小球,通过addBalls(x,y,num)函数为这个数组中增加小球:
function addBalls(x,y,num){
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){
var aBall = {
x:x+j*2*(RADIUS+1)+(RADIUS+1),
y:y+i*2*(RADIUS+1)+(RADIUS+1),
g:1.5+Math.random(),//随机一个g,即g取值在1.5-2.5之间
vx:Math.pow(-1,Math.ceil(Math.random()*1000))*4,//ceil,向上取整;-1的多少次方
//vx即为随机取值在-4或4,如果随机为偶数,则为4,否则为-4
vy:-5,
//小球颜色,随机一个索引
color:colors[Math.floor(Math.random()*colors.length)]
}
balls.push(aBall)
}
}
}
}
首先遍历digit二维数组中的digit[num]数组,如果digit[num][i][j]==1,即这个点阵[i][j]处位置需要画上小球,那么我们在这里加上一个小球,用于计时的时候让这些小球滚落。
因为我们的小球颜色,运动轨迹都是随机的,因此,我们使用随机函数来随机小球的颜色和运动轨迹,小球的颜色我们设置一个数组,在随机小球颜色中随机的即为数组中的颜色
const colors = ["#33B5E5","#0099CC","#AA66CC","#9933CC","#99CC00","#669900","#FFBB33","#FF8800","#FF4444","#CC0000"]
这样我们就可以在balls[]数组中加上小球了,接下来就可以绘制了,我们来看render函数中对于小球的绘制:
//绘制小球
for (var i = 0; i < balls.length; i++) {
cxt.fillStyle = balls[i].color;
cxt.beginPath();
cxt.arc(balls[i].x, balls[i].y, RADIUS, 0, 2*Math.PI, true);
cxt.closePath();
cxt.fill();
}
小球绘制比较简单,只需要遍历balls数组即可。
如何做出小球滚动的动画呢?我们应该发现了,对于时间和小球的绘制,我都将其放在render函数中,而同理,对于动画功能,我们也应该将其放在一个函数中,应该都将其放在update函数中,然而每一个小球动画的具体细节,还是应该封装为另一个函数,然后我们再在update中调用即可,新封住的函数为updateBalls()函数,表示每个小球的动画:
function updateBalls(){
for (var i = 0; i < balls.length; i++) {
balls[i].x += balls[i].vx;
balls[i].y += balls[i].vy;
balls[i].vy += balls[i].g;
if (balls[i].y >= WINDOW_HEIGHT - RADIUS) {
balls[i].y = WINDOW_HEIGHT - RADIUS;
balls[i].vy = -balls[i].vy*0.75;
}
}
var cnt = 0
for (var i = 0; i < balls.length; i++) {
if (balls[i].x + RADIUS>0&&balls[i].x- RADIUS<WINDOW_WIDTH) {
balls[cnt++] = balls[i]//一旦小球符和条件在画布里,则将符和的小球挤在balls数组前面
}
}
while(balls.length>Math.min(300,cnt)){
balls.pop();
}
}
首先遍历balls数组,设置小球轨迹与碰撞检测,如果碰到下边距,则令小球反弹回来,只是反弹的速度为原速度的0.75倍,这是为了更加贴合实际中的空气阻力。同时,我们需要将一些已经跑出屏幕外的小球从balls数组中删除,这样,每次更新的小球动画就完成了,我们接下来需要看的就是每次更新时,怎样调用这个动画,在update函数中:
我们在之前的写好的update函数中新添加了这些内容用于更新小球:
if (nextSeconds != curSeconds) {
if(parseInt(curHours/10) != parseInt(nextHours/10) ){
addBalls(MARGIN_LEFT+0,MARGIN_TOP,parseInt(curHours/10));
}
if(parseInt(curHours%10) != parseInt(nextHours%10) ){
addBalls(MARGIN_LEFT+15*(RADIUS+1),MARGIN_TOP,parseInt(curHours%10));
}
if(parseInt(curMinutes/10) != parseInt(nextMinutes/10) ){
addBalls(MARGIN_LEFT+39*(RADIUS+1),MARGIN_TOP,parseInt(curMinutes/10));
}
if(parseInt(curMinutes%10) != parseInt(nextMinutes%10) ){
addBalls(MARGIN_LEFT+54*(RADIUS+1),MARGIN_TOP,parseInt(curMinutes%10));
}
if(parseInt(curSeconds/10) != parseInt(nextSeconds/10) ){
addBalls(MARGIN_LEFT+78*(RADIUS+1),MARGIN_TOP,parseInt(curSeconds/10));
}
if(parseInt(curSeconds%10) != parseInt(nextSeconds%10) ){
addBalls(MARGIN_LEFT+93*(RADIUS+1),MARGIN_TOP,parseInt(curSeconds%10));
}
curShowTimeSeconds = nextShowTimeSeconds
}
updateBalls();
现在,我们大部分的内容都已经写好了,我们来看一下这个程序最主要的两个函数render函数和update函数的所有代码:
function update(){
var nextShowTimeSeconds = getCurrentShowTimeSeconds();
var nextHours = parseInt(nextShowTimeSeconds/3600);
var nextMinutes = parseInt(nextShowTimeSeconds-nextHours*3600)/60;
var nextSeconds = nextShowTimeSeconds%60;
var curHours = parseInt(curShowTimeSeconds/3600);
var curMinutes = parseInt(curShowTimeSeconds-curHours*3600)/60;
var curSeconds = curShowTimeSeconds%60;
if (nextSeconds != curSeconds) {
if(parseInt(curHours/10) != parseInt(nextHours/10) ){
addBalls(MARGIN_LEFT+0,MARGIN_TOP,parseInt(curHours/10));
}
if(parseInt(curHours%10) != parseInt(nextHours%10) ){
addBalls(MARGIN_LEFT+15*(RADIUS+1),MARGIN_TOP,parseInt(curHours%10));
}
if(parseInt(curMinutes/10) != parseInt(nextMinutes/10) ){
addBalls(MARGIN_LEFT+39*(RADIUS+1),MARGIN_TOP,parseInt(curMinutes/10));
}
if(parseInt(curMinutes%10) != parseInt(nextMinutes%10) ){
addBalls(MARGIN_LEFT+54*(RADIUS+1),MARGIN_TOP,parseInt(curMinutes%10));
}
if(parseInt(curSeconds/10) != parseInt(nextSeconds/10) ){
addBalls(MARGIN_LEFT+78*(RADIUS+1),MARGIN_TOP,parseInt(curSeconds/10));
}
if(parseInt(curSeconds%10) != parseInt(nextSeconds%10) ){
addBalls(MARGIN_LEFT+93*(RADIUS+1),MARGIN_TOP,parseInt(curSeconds%10));
}
curShowTimeSeconds = nextShowTimeSeconds
}
updateBalls();
console.log(balls.length)
}
function render(cxt){
cxt.clearRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT)
//绘制时间
var hours = parseInt(curShowTimeSeconds/3600);
var minutes = parseInt(curShowTimeSeconds-hours*3600)/60;
var seconds = curShowTimeSeconds%60;
renderDigit(MARGIN_LEFT,MARGIN_TOP,parseInt(hours/10),cxt);
renderDigit(MARGIN_LEFT+15*(RADIUS+1), MARGIN_TOP,parseInt(hours%10),cxt);
renderDigit(MARGIN_LEFT+30*(RADIUS+1),MARGIN_TOP,10,cxt);
renderDigit(MARGIN_LEFT+39*(RADIUS+1),MARGIN_TOP,parseInt(minutes/10),cxt);
renderDigit(MARGIN_LEFT+54*(RADIUS+1), MARGIN_TOP,parseInt(minutes%10),cxt);
renderDigit(MARGIN_LEFT+69*(RADIUS+1),MARGIN_TOP,10,cxt);
renderDigit(MARGIN_LEFT+78*(RADIUS+1),MARGIN_TOP,parseInt(seconds/10),cxt);
renderDigit(MARGIN_LEFT+93*(RADIUS+1), MARGIN_TOP,parseInt(seconds%10),cxt);
//绘制小球
for (var i = 0; i < balls.length; i++) {
cxt.fillStyle = balls[i].color;
cxt.beginPath();
cxt.arc(balls[i].x, balls[i].y, RADIUS, 0, 2*Math.PI, true);
cxt.closePath();
cxt.fill();
}
}
为了做到每秒都会和真实时间一样改变,我们用js中的计时器setInterval来将render函数与update函数包围
setInterval(function(){
render(context);
update();
},50
);
设定的是每50ms更新一次,可能有人会问,为什么不是1s更新一次,因为我们的倒计时就是每秒会跳动的啊?后来通过验证发现,当设置为1s更新时,会有运行延迟,每次刷新都会超过1s,我们能明显感觉到刷新,而当设置为50ms时,就是1s内页面会多次刷新,这样会让动画效果更流畅。
现在,我们的工作基本都完成了,上源码:
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>倒计时</title>
<script type="text/javascript" src="js/digit.js"></script>
<script type="text/javascript" src="js/countdown.js"></script>
</head>
<body style="height: 100%">
<h1 class="tishi">一小时倒计时:</h1>
<canvas id="canvas" style="height: 100%">当前浏览器不支持canvas,请更换浏览器后再试</canvas>
</body>
</html>
countdown.js:
var WINDOW_WIDTH = 1024
var WINDOW_HEIGHT = 600
var RADIUS = 8
var MARGIN_TOP = 60//每个数字距离上边距的距离
var MARGIN_LEFT = 30//第一个数字距离左边距的距离
var endTime = new Date()
endTime.setTime(endTime.getTime()+3600*1000)
var curShowTimeSeconds = 0//表示现在倒计时需要多少秒
balls = [];
const colors = ["#33B5E5","#0099CC","#AA66CC","#9933CC","#99CC00","#669900","#FFBB33","#FF8800","#FF4444","#CC0000"]
window.onload = function(){
WINDOW_WIDTH = document.documentElement.clientWidth
WINDOW_HEIGHT = document.documentElement.clientHeight
MARGIN_LEFT = Math.round(WINDOW_WIDTH/10)
RADIUS = Math.round(WINDOW_WIDTH*4/5/108)-1
MARGIN_TOP = Math.round(WINDOW_HEIGHT/5)
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d')
canvas.width = WINDOW_WIDTH
canvas.height = WINDOW_HEIGHT
curShowTimeSeconds = getCurrentShowTimeSeconds();
setInterval(function(){
render(context);
update();
},50
);
}
//获取当前时间与规定时间之差,返回值为秒
function getCurrentShowTimeSeconds(){
var curTime = new Date()
var ret = endTime.getTime()-curTime.getTime()//此处获得为毫秒数
ret = Math.round(ret/1000)//转化为秒
return ret>=0?ret:0;
}
function update(){
var nextShowTimeSeconds = getCurrentShowTimeSeconds();
var nextHours = parseInt(nextShowTimeSeconds/3600);
var nextMinutes = parseInt(nextShowTimeSeconds-nextHours*3600)/60;
var nextSeconds = nextShowTimeSeconds%60;
var curHours = parseInt(curShowTimeSeconds/3600);
var curMinutes = parseInt(curShowTimeSeconds-curHours*3600)/60;
var curSeconds = curShowTimeSeconds%60;
if (nextSeconds != curSeconds) {
if(parseInt(curHours/10) != parseInt(nextHours/10) ){
addBalls(MARGIN_LEFT+0,MARGIN_TOP,parseInt(curHours/10));
}
if(parseInt(curHours%10) != parseInt(nextHours%10) ){
addBalls(MARGIN_LEFT+15*(RADIUS+1),MARGIN_TOP,parseInt(curHours%10));
}
if(parseInt(curMinutes/10) != parseInt(nextMinutes/10) ){
addBalls(MARGIN_LEFT+39*(RADIUS+1),MARGIN_TOP,parseInt(curMinutes/10));
}
if(parseInt(curMinutes%10) != parseInt(nextMinutes%10) ){
addBalls(MARGIN_LEFT+54*(RADIUS+1),MARGIN_TOP,parseInt(curMinutes%10));
}
if(parseInt(curSeconds/10) != parseInt(nextSeconds/10) ){
addBalls(MARGIN_LEFT+78*(RADIUS+1),MARGIN_TOP,parseInt(curSeconds/10));
}
if(parseInt(curSeconds%10) != parseInt(nextSeconds%10) ){
addBalls(MARGIN_LEFT+93*(RADIUS+1),MARGIN_TOP,parseInt(curSeconds%10));
}
curShowTimeSeconds = nextShowTimeSeconds
}
updateBalls();
console.log(balls.length)
}
function updateBalls(){
for (var i = 0; i < balls.length; i++) {
balls[i].x += balls[i].vx;
balls[i].y += balls[i].vy;
balls[i].vy += balls[i].g;
if (balls[i].y >= WINDOW_HEIGHT - RADIUS) {
balls[i].y = WINDOW_HEIGHT - RADIUS;
balls[i].vy = -balls[i].vy*0.75;
}
}
var cnt = 0
for (var i = 0; i < balls.length; i++) {
if (balls[i].x + RADIUS>0&&balls[i].x- RADIUS<WINDOW_WIDTH) {
balls[cnt++] = balls[i]//一旦小球符和条件在画布里,则将符和的小球挤在balls数组前面
}
}
while(balls.length>Math.min(300,cnt)){
balls.pop();
}
}
function addBalls(x,y,num){
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){
var aBall = {
x:x+j*2*(RADIUS+1)+(RADIUS+1),
y:y+i*2*(RADIUS+1)+(RADIUS+1),
g:1.5+Math.random(),//随机一个g,即g取值在1.5-2.5之间
vx:Math.pow(-1,Math.ceil(Math.random()*1000))*4,//ceil,向上取整;-1的多少次方
//vx即为随机取值在-4或4,如果随机为偶数,则为4,否则为-4
vy:-5,
//小球颜色,随机一个索引
color:colors[Math.floor(Math.random()*colors.length)]
}
balls.push(aBall)
}
}
}
}
function render(cxt){
cxt.clearRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT)
//绘制时间
var hours = parseInt(curShowTimeSeconds/3600);
var minutes = parseInt(curShowTimeSeconds-hours*3600)/60;
var seconds = curShowTimeSeconds%60;
renderDigit(MARGIN_LEFT,MARGIN_TOP,parseInt(hours/10),cxt);
renderDigit(MARGIN_LEFT+15*(RADIUS+1), MARGIN_TOP,parseInt(hours%10),cxt);
renderDigit(MARGIN_LEFT+30*(RADIUS+1),MARGIN_TOP,10,cxt);
renderDigit(MARGIN_LEFT+39*(RADIUS+1),MARGIN_TOP,parseInt(minutes/10),cxt);
renderDigit(MARGIN_LEFT+54*(RADIUS+1), MARGIN_TOP,parseInt(minutes%10),cxt);
renderDigit(MARGIN_LEFT+69*(RADIUS+1),MARGIN_TOP,10,cxt);
renderDigit(MARGIN_LEFT+78*(RADIUS+1),MARGIN_TOP,parseInt(seconds/10),cxt);
renderDigit(MARGIN_LEFT+93*(RADIUS+1), MARGIN_TOP,parseInt(seconds%10),cxt);
//绘制小球
for (var i = 0; i < balls.length; i++) {
cxt.fillStyle = balls[i].color;
cxt.beginPath();
cxt.arc(balls[i].x, balls[i].y, RADIUS, 0, 2*Math.PI, true);
cxt.closePath();
cxt.fill();
}
}
function renderDigit(x,y,num,cxt){
cxt.fillStyle = '#e89abe';
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();
}
}
}
}
这样,我们炫丽的倒计时效果就做出来啦~
当然,我们也可以将其改造成时钟:
·倒计时扩展的时钟效果:
首先,不需要endTime这个变量(这个变量本身代替的是结束的时间)
除此之外,修改的焦点应当主要放在getCurrentShowTimeSeconds()中,倒计时效果中,该函数
表示现在距离倒计时结束的时间还有多少秒。而如果改成时钟,即将这个函数改为今天已经走了
多少秒即可