在慕课网上看到一位老师的电子钟,效果蛮酷,就自己模仿写了下来。这个程序有两个难点,第一是数字的坐标确定,第二个是彩色圆点的动画控制。
总结一下思路,确定点的坐标是利用一个三维数组,根据小圆点的半径计算出来的,要想每个彩色小球有不同的速度方向和颜色,我们需要每个小球都是一个对象,为此我们写一个类来生成许多个彩色小球。在绘制蓝色字体的时候,我们判断是否需要绘制彩色小球,如果需要,则拿出相应的坐标,传给小球的类,生成对象后保存在数组里面,游戏循环的时候遍历存放小球对象的数据并且调用小球的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); }