用canvas实现炫丽的计时器效果
首先看一下将要实现的效果图
接下来我们逐步实现此效果
一、 定义画布的宽高,还有小球的半径,并且定义小球的几种颜色
var WINDOW_WIDTH=1024;
var WINDOW_HEIGHT=768;
var RADIUS=6;
const colors=["#33B5E5","#0099CC","#AA66CC","#9933CC","#99CC00","#669900","#FFBB33","#FF8800","#FF4444","#CC0000"];
二、 使用canvas开始绘制画布,小球等图形
window.onload=function(){
WINDOW_WIDTH=document.body.clientWidth;
WINDOW_HEIGHT=document.body.clientHeight;
var canvas=document.getElementById("canvas_onmpw");
var context=canvas.getContext("2d");
canvas.width=WINDOW_WIDTH;
canvas.height=WINDOW_HEIGHT;
setInterval(
function(){
drawBalls(context);
moveball();
},50);
}
三、 定义drawBalls() 和 moveball()函数
function drawBalls(cxt){
cxt.clearRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT);
var times=getTime();
var hours=parseInt(times/3600);
var minutes=parseInt((times-hours*3600)/60);
var seconds=parseInt(times%60);
drawDigit(parseInt(hours/10),0,cxt);
drawDigit(hours%10,digit[0][0].length,cxt);
drawDigit(10,digit[0][0].length*2,cxt);
drawDigit(parseInt(minutes/10),digit[0][0].length*2+digit[10][0].length,cxt);
drawDigit(minutes%10,digit[0][0].length*3+digit[10][0].length,cxt);
drawDigit(10,digit[0][0].length*4+digit[10][0].length,cxt);
drawDigit(parseInt(seconds/10),digit[0][0].length*4+digit[10][0].length*2,cxt);
drawDigit(seconds%10,digit[0][0].length*5+digit[10][0].length*2,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();
}
}
函数体中又有自定义函数drawDigit(),这个函数是用来实现时间的样式的。关于此函数的定义,我们在第四步的时候实现,下面我们看moveball()函数的定义
function moveball(){
//得到当前的时间
var nextShowTime=getTime();
var nextHour=parseInt(nextShowTime/3600);
var nextMinutes=parseInt((nextShowTime-nextHour*3600)/60);
var nextSeconds=nextShowTime%60;
var curHour=parseInt(currentshowtime/3600);
var curMinutes=parseInt((currentshowtime-curHour*3600)/60);
var curSeconds=currentshowtime%60;
if(nextSeconds!=curSeconds){
if(parseInt(nextHour/10)!=parseInt(curHour/10)){
addBalls(100,100,parseInt(nextHour/10));
}
if(nextHour%10!=curHour%10){
addBalls(100+digit[0][0].length*(2*(RADIUS+2)),100,nextHour%10);
}
if(parseInt(curMinutes/10)!=parseInt(nextMinutes/10)){
addBalls(100+(digit[0][0].length*2+digit[10][0].length)*(2*(RADIUS+2)),100,parseInt(nextMinutes/10));
}
if(curMinutes%10!=nextMinutes%10){
addBalls(100+(digit[0][0].length*3+digit[10][0].length)*(2*(RADIUS+2)),100,nextMinutes%10);
}
if(parseInt(curSeconds/10)!=parseInt(nextSeconds/10)){
addBalls(100+(digit[0][0].length*4+digit[10][0].length*2)*(2*(RADIUS+2)),100,parseInt(nextSeconds/10));
}
if(curSeconds%10!=nextSeconds%10){
addBalls(100+(digit[0][0].length*5+digit[10][0].length*2)*(2*(RADIUS+2)),100,nextSeconds%10);
}
currentshowtime=nextShowTime;
}
move();
console.log(balls.length);
}
同样此函数中涉及到两个自定义函数,addBalls()(此函数是为了实现将要改变的数字上面的小球加入数组中,以实现这些小球的斜抛运动)和 move()(实现由addBalls()加入数组中的小球的斜抛运动)。这两个函数将在第五步中实现
四、 定义drawDigit()函数
function drawDigit(num,dis,cxt){
var tempball={x:100,y:100,radius:RADIUS,color:"#FF0000"};
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){
tempball.x=100+dis*(2*(RADIUS+2))+j*(2*(RADIUS+1));
tempball.y=100+i*2*(RADIUS+1);
drawball(tempball,cxt);
}
}
}
}
此函数中涉及到drawball()函数,此函数功能是绘制时间小球。其定义我们在第六步中实现
五、 定义addBalls() 和 move()函数
function addBalls(ax,ay,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:ax+j*(2*(RADIUS+1)),
y:ay+i*(2*(RADIUS+1)),
gy:8+Math.random(),
vx:Math.pow(-1,Math.ceil(Math.random()*1000))*5,
vy:-8,
color:colors[Math.floor(Math.random()*colors.length)]
};
balls.push(aball);
}
}
}
}
function move(){
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].vy+balls[i].gy*0.05;
}
var count=0;
for(var j=0;j<balls.length;j++){
if(balls[j].y<WINDOW_HEIGHT){
balls[count++]=balls[j];
}
}
while(balls.length>count){
balls.pop();
}
}
在addBalls()函数中有balls.push()将小球放入数组中,如果无限制的将小球加入数组,那么数组会越来越大,所以在move()函数中定义又根据小球是否超出边界来将小球从数组中再取出,以达到数组中小球数量的稳定。
六、 实现drawball()函数
function drawball(ball,cxt){
cxt.fillStyle=ball.color;
cxt.beginPath();
cxt.arc(ball.x,ball.y,ball.radius,0,2*Math.PI,true);
cxt.closePath();
cxt.fill();
}
实现以上六个步骤,就可以实现计时器的效果。如果有什么问题,欢迎在下面留言讨论,大家共同提高。
相关文章
Do you understand JavaScript closures?
发布时间:2025/02/21 浏览次数:108 分类:JavaScript
-
The function of a closure can be inferred from its name, suggesting that it is related to the concept of scope. A closure itself is a core concept in JavaScript, and being a core concept, it is naturally also a difficult one.
Do you know about the hidden traps in variables in JavaScript?
发布时间:2025/02/21 浏览次数:178 分类:JavaScript
-
Whether you're just starting to learn JavaScript or have been using it for a long time, I believe you'll encounter some traps related to JavaScript variable scope. The goal is to identify these traps before you fall into them, in order to av
How much do you know about the Prototype Chain?
发布时间:2025/02/21 浏览次数:150 分类:JavaScript
-
The prototype chain can be considered one of the core features of JavaScript, and certainly one of its more challenging aspects. If you've learned other object-oriented programming languages, you may find it somewhat confusing when you start
如何在 JavaScript 中合并两个数组而不出现重复的情况
发布时间:2024/03/23 浏览次数:86 分类:JavaScript
-
本教程介绍了如何在 JavaScript 中合并两个数组,以及如何删除任何重复的数组。