Codog

关注微信公众号:Codog代码狗

0%

Canvas(五)动画实例:烟花效果

知道了canvas动画基本原理后我们可以尝试绘制比较精美的动画了,以烟花为例。

会涉及到基础的三角函数、元素运动效果仿真。

先来想想较为逼真的烟花效果应该是什么样子的:从中心爆炸均匀向西周扩散,每个元素的运动速度有快有慢,烟花的颜色应该是不同的,且纵向有加速度,横向有阻力,最后,随着时间元素应该慢慢变淡,最终消失。

之前说过,canvas的动画效果实际是每一帧绘制一幅图,模拟动画效果,那么诸多元素向四周均匀扩散,实际是各自的运动矢量是向四周扩散的。这里指的运动矢量通常用横纵方向来表示。

在三角函数中,圆上的各点坐标可以由它与x轴正方向的角度计算得出,Math提供的sincos方法就可以用来计算具体数值。

假设一个烟花由300个元素组成,那么将这300个元素的运动矢量(包括方向和大小)均匀放置在一个圆上的话,每个元素的运动矢量可以如此计算得出:

一个圆的角度是Math.PI * 2。

1
2
3
4
5
6
7
const angleIncrement = Math.PI * 2 / 300;
for(let i = 0; i < 300; i ++) {
firework.push(new Fire({
x: Math.sin(i * angleIncrement)
y: Math.cos(i * angleIncrement)
}))
}

这样下来就有了向四周均匀扩散的300个元素了,然后再乘以随机值就可以模拟运动快慢的效果了。

canvas上下文本身提供了globalAlpha通道,可以控制绘制(fill, stroke)的透明度。但在进行修改时会对全局进行修改,我们可以保存上下文状态,绘制后再恢复之前的状态。

这就需要借助save和restore方法,它的效果类似git的版本管理,save方法相当于一个提交保存操作,记录了当前的上下文状态,之后可以任意对上下文对象进行修改,restore方法相当于回退,回退到之前的上下文状态。避免多个绘制方法的上下文之前的互相干扰。

常见使用方式:

1
2
3
4
5
6
7
8
9
10
function foo() {
// save方法记录一个状态
ctx.save();
// 修改了上下文状态
ctx.globalAlpha = this.alpha;
// do something...
ctx.closePath()
// 回退上个save方法记录的快照
ctx.restore();
}

实例:(点击画布区域)

推荐一个youtube频道