canvas之倒计时数字钟的具体绘制

本文详细介绍了如何利用HTML5的canvas元素来绘制一个倒计时数字钟。通过context.arc方法画出弧线构成钟面,并利用beginPath和closePath控制路径绘制数字。倒计时程序中,数字被表示为10*7的二维数组,冒号则用10*4的尺寸。核心代码分别在digit.js和countDown.js中实现。

context

arc画弧线



context.arc(300,300,200,0,0.5*Math.pi*(i+1)/10)表示以300,300为圆心

200为半径,0到1.5pi,第六个参数指定为顺时针还是逆时针(true)

//beginPath和closePath

倒计时程序:


数字用10*7的二维数组,冒号用10*4

digit.js

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]
        ]//:
    ];

countDown.js

//获取浏览器的宽度和高度
//这里需要设置body和canvas的高度为100%
var WINDOW_WIDTH=document.body.clientWidth;
var WINDOW_HEIGHT=document.body.clientHeight;


var MARGIN_LEFT=Math.round(WINDOW_WIDTH/10);
var MARGIN_TOP=Math.round(WINDOW_HEIGHT/5);
var RADIUS=Math.round(WINDOW_WIDTH*4/5/108)-1;


//设置结束时间
//这里月份的设置,默认是从0-11的,所以九月份就是8
var ENDTIME=new Date();
ENDTIME.setTime(ENDTIME.getTime()+3600*1000*24*2);

var curShowTimeSeconds=0;

var balls = [];
//设置小球可能出现的颜色
const colors = ["#33B5E5","#0099CC","#AA66CC","#9933CC","#99CC00","#669900","#FFBB33","#FF8800","#FF4444","#CC0000"];

window.onload=function(){
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext('2d');
    canvas.width=WINDOW_WIDTH;
    canvas.height=WINDOW_HEIGHT;

    //获取当前显示的时间对应的秒数
    curShowTimeSeconds=getCurrentShowTimeSeconds();

    setInterval(function(){
        //绘制
        render(ctx);
        //更新
        updates();
    },50);


}
function getCurrentShowTimeSeconds(){
    //获取当前时间
    var curTime=new Date();
    //返回结束时间对应的毫秒数减去当前时间的毫秒数的结果
    var ret=ENDTIME.getTime()-curTime.getTime();
    //把毫秒数转换成秒,并转换成整数
    ret=Math.round(ret/1000);
    return ret>0?ret:0;
}
//更新页面
function updates(){
    var nextShowTimeSecond=getCurrentShowTimeSeconds();
    var nextHours=parseInt(nextShowTimeSecond/3600);
    var nextMinutes=parseInt((nextShowTimeSecond-nextHours*3600)/60);
    var nextSeconds=parseInt(nextShowTimeSecond%60);

    var curHours=parseInt(curShowTimeSeconds/3600);
    var curMinutes=parseInt((curShowTimeSeconds-curHours*3600)/60);
    var curSeconds=parseInt(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 + 16*(RADIUS+1) , MARGIN_TOP , parseInt(curHours%10) );
        }
        if( parseInt(curMinutes/10) != parseInt(nextMinutes/10) ){
            addBalls( MARGIN_LEFT + 40*(RADIUS+1) , MARGIN_TOP , parseInt(curMinutes/10) );
        }
        if( parseInt(curMinutes%10) != parseInt(nextMinutes%10) ){
            addBalls( MARGIN_LEFT + 56*(RADIUS+1) , MARGIN_TOP , parseInt(curMinutes%10) );
        }
        if( parseInt(curSeconds/10) != parseInt(nextSeconds/10) ){
            addBalls( MARGIN_LEFT + 80*(RADIUS+1) , MARGIN_TOP , parseInt(curSeconds/10) );
        }
        if( parseInt(curSeconds%10) != parseInt(nextSeconds%10) ){
            addBalls( MARGIN_LEFT + 96*(RADIUS+1) , MARGIN_TOP , parseInt(nextSeconds%10) );
        }


        curShowTimeSeconds=nextShowTimeSecond;
    }
    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.6;
        }
    }

    //对页面进行性能优化
    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];
        }
    }
    while(balls.length>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(),
                    vx:Math.pow( -1 , Math.ceil( Math.random()*1000 ) ) * 4,
                    vy:-5,
                    color: colors[ Math.floor( Math.random()*colors.length ) ]
                };
                balls.push( aBall )    ;
            }
        }
    }
}


function render(ctx){
    //清除之前画的内容
    ctx.clearRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT);
    var hours=parseInt(curShowTimeSeconds/3600);
    var minutes=parseInt((curShowTimeSeconds-hours*3600)/60);
    var seconds=parseInt(curShowTimeSeconds%60);
    //小时的绘制
    //设置允许空格
    renderDigit(MARGIN_LEFT,MARGIN_TOP,parseInt(hours/10),ctx);
    //x、y的位置为加上第一个数字占用的空间,加1是为了留下一定的空格
    renderDigit(MARGIN_LEFT+16*(RADIUS+1),MARGIN_TOP,parseInt(hours%10),ctx);
    renderDigit(MARGIN_LEFT+32*(RADIUS+1),MARGIN_TOP,10,ctx);

    //分钟的绘制
    renderDigit(MARGIN_LEFT+40*(RADIUS+1),MARGIN_TOP,parseInt(minutes/10),ctx);
    renderDigit(MARGIN_LEFT+56*(RADIUS+1),MARGIN_TOP,parseInt(minutes%10),ctx);
    renderDigit(MARGIN_LEFT+72*(RADIUS+1),MARGIN_TOP,10,ctx);

    //秒钟的绘制
    renderDigit(MARGIN_LEFT+80*(RADIUS+1),MARGIN_TOP,parseInt(seconds/10),ctx);
    renderDigit(MARGIN_LEFT+96*(RADIUS+1),MARGIN_TOP,parseInt(seconds%10),ctx);

    //绘制弹跳的小球
    for( var i = 0 ; i < balls.length ; i ++ ){
        ctx.fillStyle=balls[i].color;

        ctx.beginPath();
        ctx.arc( balls[i].x , balls[i].y , RADIUS , 0 , 2*Math.PI , true );
        ctx.closePath();

        ctx.fill();
    }

}

//绘制时分秒的数字
function renderDigit(x,y,num,ctx){
    ctx.fillStyle="rgb(0,102,153)";
    //循环digit数组里面的数据
    //循环digit[0],则表示digit里面的第一个数组
    //digit[0]也是一个数组,他的长度是10

    for (var i=0;i<digit[num].length;i++) {
        //循环digit[0]第i个数组的长度
        for (var j=0;j<digit[num][i].length;j++) {
            //如果数字是1的话则绘制一个圆
            if(digit[num][i][j]==1){
                ctx.beginPath();
                ctx.arc(x+j*2*(RADIUS+1)+(RADIUS+1),y+i*2*(RADIUS+1)+(RADIUS+1),RADIUS,0,2*Math.PI,true);
                ctx.closePath();
                ctx.fill();
            }
        }
    }
}
index.html
<!DOCTYPE html>
<html style="height: 100%">
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body style="height:100%;width: 100%;">
    <canvas id="canvas" style="height:100%">
        当前浏览器不支持Canvas,请更换浏览器后再试
    </canvas>

    <script src="digit.js"></script>
    <script src="countdown.js"></script>
</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值