基础知识

动画循环的三要素:

  • 清除画布
  • 更新需要绘制的对象
  • 在画布中重新绘制对象

注意 在清除对象之前不要绘制对象

创建动画循环:

记忆形状——对象

引入:如何准确记忆要绘制的对象的内容及位置?上一个基础动画采用的是:设置一个变量来保存对象的位置值x。但若需要绘制多个动画形状就得写很多类似的代码,且不易管理。所以可以考虑使用对象和数组来实现。

  • 通过使用对象的属性和方法,可以为某些对象定义模板。
  • 仅定义还不够,还需要通过数组来存储形状对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var Shape = function(x, y) {
this.x = x;
this.y = y;
}
var shapes = new Array();
for(var i=0; i<10; i++) {
shapes.push(new Shape());
}
function animate(){
……
// 更新并绘制
for (var i = 0; i < shapes.length; i++) {
shapes[i].x++;
context.fillRect(x, y, 10, 10);
}
……
}

随机产生形状——Math.random()

1
2
3
4
5
6
var Shape = function(){
this.x = Math.random()*canvas.width;
this.y = Math.random()*canvas.height;
this.width = Math.random()*50;
//this.height = this.width;
}

圆周运动——三角函数

定义:形状在圆周的右边缘作为角度为0弧度的位置;a是角度,r是半径,x是邻边,y是对边。
在每次动画循环中,只需增加圆周上的形状的角度,就可以使形状沿着圆周运动。
需要解决的问题:如何计算圆周上形状的(x,y)坐标值?
在已知角度a的条件下,根据三角函数有:
$$
sin(a) = \frac{y}{r},
cos(a) = \frac{x}{r}
$$
由此可以计算(x,y)坐标:
$$
x = r \ast Math.cos(a) \\
y = r \ast Math.sin(a)
$$
仍就上述例子,首先在Shape类中添加半径和初始化角度:

1
2
this.radius = Math.random()*30; // 运动半径在0~30
this.angle = 0;

再计算(x,y)坐标及角度变化:

1
2
3
4
5
6
var x = shapes[i].x + (shapes[i].radius * Math.cos(shapes[i].angle * (Math.PI/180))),
y = shapes[i].y + (shapes[i].radius * Math.sin(shapes[i].angle * (Math.PI/180)));
shapes[i].angle += Math.random()*10; // 角速度随机
if(shapes[i].angle > 360) {
shapes[i].angle = 0;
}

到此,基本的圆周运动就可以实现。当然还可以做点修饰。

添加随机颜色

Shape类中添加rgba属性:

1
2
3
4
this.r = Math.floor(Math.random()*255);
this.g = Math.floor(Math.random()*255);
this.b = Math.floor(Math.random()*255);
this.a = Math.floor(Math.random()*255);

绘制圆形形状

1
2
3
4
5
6
7
// 设置每个块的颜色
context.fillStyle = 'rgba(' +shapes[i].r+ ',' +shapes[i].g+ ',' +shapes[i].b+ ',' +shapes[i].a+ ')';
// 绘制圆形
context.beginPath();
context.arc(x+shapes[i].width/2, y+shapes[i].width/2, shapes[i].width/2, Math.PI*2, false);
context.closePath();
context.fill();

最终效果


参考资料:《Foundation HTML5 Canvas For Games and Entertainment》Chapter 6 Authors: Hawkes, Rob