利用canvas绘制绚丽的电子钟

在慕课网上看到一位老师的电子钟,效果蛮酷,就自己模仿写了下来。这个程序有两个难点,第一是数字的坐标确定,第二个是彩色圆点的动画控制。

总结一下思路,确定点的坐标是利用一个三维数组,根据小圆点的半径计算出来的,要想每个彩色小球有不同的速度方向和颜色,我们需要每个小球都是一个对象,为此我们写一个类来生成许多个彩色小球。在绘制蓝色字体的时候,我们判断是否需要绘制彩色小球,如果需要,则拿出相应的坐标,传给小球的类,生成对象后保存在数组里面,游戏循环的时候遍历存放小球对象的数据并且调用小球的draw()方法即可,同时注意对小球生命周器的检测,如果已经消失在视野,小球就应该结束他的生命周期了。、

另外一个难点,看代码式子了,很好理解。

 

数字绘制的数据: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]
        ]//:
    ];

 

彩色小球类:ball.js

var ballObj = function (x,y) {
    this.x = x;
    this.y = y;

    this.alive = false;

    this.vy = 0;//y方向的速度
    this.vx = 0;//x方向的速度
    this.g = .2;//纵向加速度
    this.xg = 0;//横向加速度

    this.color = '';
};

ballObj.prototype.init = function () {
    var k = Math.random() < .5 ? 1 : -1;
    var R = Math.ceil(Math.random() * 255);
    var G = Math.ceil(Math.random() * 255);
    var B = Math.ceil(Math.random() * 255);

    this.alive = false;
    this.vy = Math.random();
    this.xg = Math.random() * 2;
    this.vx = 5 * k * this.xg;
    this.r = radius;
    this.color = R + ',' + G + ',' + B;
};

ballObj.prototype.born = function () {
    this.alive = true;
};


//go out canvas
ballObj.prototype.kill = function () {

    if (this.x + radius < 0 || this.x - radius > canWidth) {
        this.alive = false;
    }

    //碰到地板反弹
    if (this.y + radius > canHeight) {
        this.y = canHeight - radius;
        this.vy = -this.vy * .6;
    }
};

ballObj.prototype.draw = function () {
    if (this.alive) {
        ctx.save();
        ctx.beginPath();
        ctx.fillStyle = 'rgb(' + this.color + ')';
        ctx.arc(this.x,this.y,this.r,0,2 * Math.PI);
        ctx.closePath();
        ctx.fill();
        ctx.restore();
        this.vy += this.g;
        this.y += this.vy;

        this.x += this.vx;
    }

    //改变速度
    this.y += this.vy;
    this.vy += this.g;
};

 

核心程序文件:main.js

var canWidth = 1024;
var canHeight = 768;
var radius = 8;
var marLeft = 30;
var marTop = 30;

var canvas;
var ctx;

var ball = [];
var posX = [];

var hour;
var minute;
var second;
var oldTime = []; //old time

window.onload = gameInit;

function gameInit() {
    canvas = document.getElementById('canvas');
    ctx = canvas.getContext('2d');

    canvas.width = canWidth;
    canvas.height = canHeight;

    //start position
    posX = [
        marLeft,
        marLeft + 15 * (radius + 1),
        marLeft + 30 * (radius + 1),
        marLeft + 39 * (radius + 1),
        marLeft + 54 * (radius + 1),
        marLeft + 69 * (radius + 1),
        marLeft + 78 * (radius + 1),
        marLeft + 93 * (radius + 1)
    ];

    //time
    hour = new Date().getHours();
    minute = new Date().getMinutes();
    second = new Date().getSeconds();

    oldTime = [
        parseInt(hour / 10),
        hour % 10,
        10,
        parseInt(minute / 10),
        minute % 10,
        10,
        parseInt(second / 10),
        second % 10
    ];


    gameLoop();
}

function gameLoop() {

    //清空画布
    ctx.clearRect(0,0,canWidth,canHeight);

    hour = new Date().getHours();
    minute = new Date().getMinutes();
    second = new Date().getSeconds();

    var num = [
        parseInt(hour / 10),
        hour % 10,
        10,
        parseInt(minute / 10),
        minute % 10,
        10,
        parseInt(second / 10),
        second % 10
    ];

    //draw time
    for (var i = 0; i < num.length; i++) {
        renderDigit(posX[i],num[i],ctx,oldTime[i] == num[i]);
    }

    oldTime = num;

    //draw color ball
    for (var k = 0; k < ball.length; k++) {
        ball[k].kill();
        ball[k].draw();

        if (ball[i].alive == false) {
            ball.splice(i,1);
        }
    }

    requestAnimationFrame(gameLoop);
}

function renderDigit(x,num,ctx,equ) {
    ctx.fillStyle = 'rgb(0,102,153)';

    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 aX = x + j * 2 * (radius + 1) + radius + 1;
                var aY = marTop + i * 2 * (radius + 1) + radius + 1;

                ctx.beginPath();
                ctx.arc(aX,aY,radius,0,2 * Math.PI);
                ctx.closePath();
                ctx.fill();

                //拿到需要的彩色小球的坐标
                if (!equ) {
                    bornBall(aX,aY);
                }
            }
        }
    }
}

//创建小球对象并且放到数组
function bornBall(x,y) {
    var obj = new ballObj(x,y);
    obj.init();
    obj.born();
    ball.push(obj);
}

 

posted @ 2017-07-06 16:46  菲菲菲菲翔  阅读(326)  评论(0编辑  收藏  举报