简单的粒子动画

demo

canvas动画套路

canvas 本意画布,应该就是画油画的那种,因此一次绘画其实只能画出一副画面。但是动画也只不过是多幅画面的连续而已。如果我们创建出连续打多幅画面,就产生了动画。

但通常我们只创建一个 canvas 来进行整个动画,因此,当后一副画面被绘画的时候,前一副画面是需要被擦除的ctx.clearRect()。所以我们需要一些对象imgObj来记录当前画面中一些元素的位置。

所以整的来讲就是

  1. 擦干净画布 ctx.clearRect()
  2. 计算当前绘画元素imgObj的位置
  3. 将元素imgObj画在画布上
  4. 回到步骤1
1
2
3
4
5
6
let loop = () => {
clearCanvas();
calculation();
drawSomething();
window.requestAnimationFrame(loop);
}

使用 requestAnimationFrame 而非 setTimeout 以获得更好的性能。

创建粒子

我们需要一个坐标来表示粒子被画在画布的哪个位置,同时动态的粒子,还需要一个表示其运动的速度。

1
2
3
4
5
6
let particle = {
centerX: 0,
centerY: 0,
speedX: 1,
speedY: 1
}

这样一个粒子的运动信息就可以被记录下来了。

以上的单个粒子还可以加上例如颜色,半径大小等更多的信息。

初始化一组粒子信息

1
2
3
4
5
6
7
8
9
let particleArr = [];
for (let i = 0; i < PARTICLE_NUM; i++) {
particleArr.push({
centerX: random(cWidth),
centerY: random(cHeight),
speedX: rando 大专栏  简单的粒子动画m(SPEED) * randomDir(),
speedY: random(SPEED) * randomDir()
});
}

绘制粒子

循环调用 canvas API 即可。

粒子更新

如果在绘制粒子前不做更新,那我们每次看到的都是同一幅画面,那整个动画就是静止的。

在这一步,之前创建粒子时保存下来的粒子位置以及速度就用上了。

我们可以简单地通过记录的速度来确定当前粒子应该在的位置。

1
2
3
4
let calcParticle = (particle) => {
particle.centerX += particle.speedX;
particle.centerY += particle.speedY;
}

这样就能使整个画面动起来。

但是如果仅仅这样,在不一会儿之后,我们的画布上就不存在粒子了,因为所有粒子沿着初始化的方向不停运动而“逃”到了画布之外。因此,我们在计算的时候再简单地加上一个碰撞检测 (当粒子半径足够小,运动速度不大的时候) ,当判断粒子位置超出画布的时候将速度反向。

1
2
3
4
5
6
7
8
9
10
let calcParticle = (particle) => {
particle.centerX += particle.speedX;
particle.centerY += particle.speedY;
if (particle.centerX < 0 || particle.centerX > cWidth) {
particle.speedX *= -1;
}
if (particle.centerY < 0 || particle.centerY > cHeight) {
particle.speedY *= -1;
}
}

X轴与Y轴各司其职。

绘制网线

逐个判断粒子间的距离,再通过最大距离计算网线的透明度。然后 ctx.lineTo() 两个粒子的中心即可。

END

粒子过多的时候回明显卡顿,而速度过大的时候会感觉动画似乎并不连贯。

猜你喜欢

转载自www.cnblogs.com/liuzhongrong/p/11874829.html