前面的话
本文将使用canvas实现粒子时钟效果
效果展示
点阵数字
digit.js是一个三维数组,包含的是0到9以及冒号(digit[10])的二维点阵。每个数字的点阵表示是7*10大小的二维数组
通过遍历数字点阵的二维数组,当该位置的值为1时,则绘制一个粒子,否则不绘制
将绘制数字的函数命名为renderDigit()。在该函数中,将粒子绘制为一个小圆。小圆的半径为R,小圆所占据的矩形宽(高)为2(R+1)。由于数字点阵是10*7的二维数组,所以一个数字的宽度为14(R+1),高度为20(R+1)
假设数字的高度为100px,则小圆的半径R=4
<div
id="test">
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>7</button>
<button>8</button>
<button>9</button>
<button>10</button>
</div>
<canvas
id="canvas">当前浏览器不支持canvas,请更换浏览器后再试</canvas>
<script>
var
canvas = document.getElementById('canvas');
if(canvas.getContext){
var
cxt = canvas.getContext('2d');
function
renderDigit(num){
//重置画布宽度,达到清空画布的效果
canvas.height
= 100;
var
R = canvas.height/20-1;
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(j*2*(R+1)+(R+1),i*2*(R+1)+(R+1),R,0,2*Math.PI);
cxt.closePath();
cxt.fill();
}
}
}
}
var
test
= document.getElementById('test');
test.onclick
= function(e){
e
= e || event;
var
target
= e.target || e.srcElement;
if(!isNaN(target.innerHTML)){
renderDigit(target.innerHTML);
}
}
}
</script>
|
时钟实现
在上一步的点阵数字的基础上,实现一个粒子时钟。将时钟实现的函数命名为digitTime(),时钟实现由获取时间数据和渲染时钟两部分组成
【时间数据】
最简单的时钟形式由两位的小时、两位的分钟和两位的秒钟组成,中间用冒号隔开。通过日期对象Date来获取当前时间,以及当前的小时、分钟和秒钟。但是,最终需要得到的是数字表示的时钟
比如12:02:36的时间数据的表示形式为data[1,2,10,0,2,10,3,6]
【渲染时钟】
获取到时间数据后,通过循环使用renderDigit()来渲染时钟中的每一个数字。此时,有一个需要改变的地方是arc()函数中的x坐标,否则它们将叠加在一起
为了将时钟数字表示更加清晰在每个数字之间增加一定的间距。每个数字的宽度是14(R+1),假设data数组中7个数字的索引为index,则每个数字的起始X坐标可以等于14(R+2)*index
最后通过定时器每间隔一段时间后更新时间
<canvas
id="canvas"
style="width:400px;">当前浏览器不支持canvas,请更换浏览器后再试</canvas>
<script>
var
canvas = document.getElementById('canvas');
if(canvas.getContext){
var
cxt = canvas.getContext('2d');
canvas.height
= 100;
canvas.width
= 700;
function
renderDigit(index,num){
var
R = canvas.height/20-1;
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(14*(R+2)*index
+ j*2*(R+1)+(R+1),i*2*(R+1)+(R+1),R,0,2*Math.PI);
cxt.closePath();
cxt.fill();
}
}
}
}
function
digitTime(){
/*获取时间数据*/
var
temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
//存储时间数字,由十位小时、个位小时、冒号、十位分钟、个位分钟、冒号、十位秒钟、个位秒钟这7个数字组成
var
data = [];
data.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
/*渲染时钟*/
//重置画布宽度,达到清空画布的效果
canvas.height
= 100;
for(var
i
= 0;
i < data.length; i++){
renderDigit(i,data[i]);
}
}
digitTime();
clearInterval(oTimer);
var
oTimer
= setInterval(function(){
digitTime();
},500);
}
</script>
|
随机抛物线
这节的随机抛物线运动是下节粒子动画的预备节。以DOM节点的投掷碰壁为基础,利用canvas实现一个小球的随机抛物线运动
将小球的运动拆分为x轴和y轴运动。x轴做匀速运动,y轴先做向上的减速运动,再做向下的加速运动。当小球离开画布区域时,停止定时器
<canvas
id="canvas"
style="width:500px;">当前浏览器不支持canvas,请更换浏览器后再试</canvas>
<script>
var
canvas = document.getElementById('canvas');
if(canvas.getContext){
var
cxt = canvas.getContext('2d');
//声明canvas的宽高
var
H = 100,W = 700;
canvas.height
= H;
canvas.width
= W;
//存储时间数据
var
data = [];
//存储运动的小球
var
balls = [];
//设置粒子半径
var
R = canvas.height/20-1;
(function(){
var
temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
//存储时间数字,由十位小时、个位小时、冒号、十位分钟、个位分钟、冒号、十位秒钟、个位秒钟这7个数字组成
data.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
})();
/*生成点阵数字*/
function
renderDigit(index,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){
cxt.beginPath();
cxt.arc(14*(R+2)*index
+ j*2*(R+1)+(R+1),i*2*(R+1)+(R+1),R,0,2*Math.PI);
cxt.closePath();
cxt.fill();
}
}
}
}
/*更新时钟*/
function
updateDigitTime(){
var
changeNumArray = [];
var
temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
var
NewData = [];
NewData.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
for(var
i
= data.length-1;
i >=0 ; i--){
//时间发生变化
if(NewData[i]
!== data[i]){
//将变化的数字值和在data数组中的索引存储在changeNumArray数组中
changeNumArray.push(i+'_'+(Number(data[i])+1)%10);
}
}
//增加小球
for(var
i = 0; i< changeNumArray.length;
i++){
addBalls.apply(this,changeNumArray[i].split('_'));
}
data
= NewData.concat();
}
/*更新小球状态*/
function
updateBalls(){
for(var
i
= 0;
i < balls.length; i++){
balls[i].stepY
+= balls[i].disY;
balls[i].x
+= balls[i].stepX;
balls[i].y
+= balls[i].stepY;
if(balls[i].x
> W + R || balls[i].y > H + R){
balls.splice(i,1);
i--;
}
}
}
/*增加要运动的小球*/
function
addBalls(index,num){
var
numArray = [1,2,3];
var
colorArray = ["#3BE","#09C","#A6C","#93C","#9C0","#690","#FB3","#F80","#F44","#C00"];
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
ball = {
x:14*(R+2)*index
+ j*2*(R+1)+(R+1),
y:i*2*(R+1)+(R+1),
stepX:Math.floor(Math.random()
* 4 -2),
stepY:-2*numArray[Math.floor(Math.random()*numArray.length)],
color:colorArray[Math.floor(Math.random()*colorArray.length)],
disY:1
};
balls.push(ball);
}
}
}
}
/*渲染*/
function
render(){
//重置画布宽度,达到清空画布的效果
canvas.height
= 100;
//渲染时钟
for(var
i
= 0;
i < data.length; i++){
renderDigit(i,data[i]);
}
//渲染小球
for(var
i
= 0;
i < balls.length; i++){
cxt.beginPath();
cxt.arc(balls[i].x,balls[i].y,R,0,2*Math.PI);
cxt.fillStyle
= balls[i].color;
cxt.closePath();
cxt.fill();
}
}
clearInterval(oTimer);
var
oTimer
= setInterval(function(){
//更新时钟
updateDigitTime();
//更新小球状态
updateBalls();
//渲染
render();
},50);
}
</script>
|
公告栏扩展
将canvas粒子时钟js部分封装为canvasTime.js,在公告栏添加如下代码,即可以实现在公告栏插入时钟的效果
<canvas
id="canvas"
style="width:100%;"
height="100"
width="700">当前浏览器不支持canvas,请更换浏览器后再试</canvas>
|
原文地址:http://www.cnblogs.com/xiaohuochai/p/6368039.html