requestAnimationFrame()
动画原理:人的视觉暂留为0.1-0.4s,当静态图片更迭速度快过视觉暂留的时间,人眼看到的就是连贯的变化。Canvas动画原理是不停地清除和重绘。
requestAnimationFrame()是setInterval()和setTimeout()的优化,主要用于动画。该方法需要传入一个回调函数作为参数,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。
若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用window.requestAnimationFrame()。
参考:
https://www.cnblogs.com/aaronjs/p/4283109.html
https://blog.csdn.net/vhwfr2u02q/article/details/79492303
cancelAnimationFrame()
重新切换到canvas时,如果没有清除之前的动效,则会出现动效叠加的情况,即canvas会生成一个新动效叠加到之前的动效上,会出现移动加快等情况。
所以每次在使用requestAnimationFrame()时,建议配合使用cancelAnimationFrame()。
cancelAnimationFrame(animationF);
animationF = requestAnimationFrame(this.showCanvas);
移动
1. 移动的本质
动画的动指“移动”,移动的本质是从一个点到另一个点。
我们需要确定四个变量来实现对移动的控制:
- t 当前时间
- b 初始值
- c 变化量
- d 持续时间
例如,我们要用5秒从(0,0)移动到(0,100),则:b为起点(0,0),我们移动的量为100,则c等于100,d为5,t是范围为0~5的一个变量。
文章开头,我们说动画的本质是擦除和重绘。以移动为例,我们每次重绘的图像的位置需要按一定规律变化,才能在视觉上产生移动的效果。此处的规律指的就是不同的移动算法。
我们先来做一道简单的数学题:
一个正方形要花费5秒从A点匀速运动到B点,A点(0,0),B点(0,100),问:第3秒的时候正方形的位置?
100*3/5=60
第3秒的位置为(0,60)
匀速运动公式:c*t/d+b
2. 运动算法
匀速运动(Linear)是最简单的移动形式,除此外,移动的方式有很多种,大体可分为三大类:
- easeIn 缓入
- easeOut 缓出
- easeInOut 淡入淡出
Quad, Cubic等等都是经典的动画运动算法名称,完整列表如下:
Linear:线性匀速运动效果;
Quadratic:二次方的缓动(t^2);
Cubic:三次方的缓动(t^3);
Quartic:四次方的缓动(t^4);
Quintic:五次方的缓动(t^5);
Sinusoidal:正弦曲线的缓动(sin(t));
Exponential:指数曲线的缓动(2^t);
Circular:圆形曲线的缓动(sqrt(1-t^2));
Elastic:指数衰减的正弦曲线缓动;
Back:超过范围的三次方缓动((s+1)*t^3 – s*t^2);
Bounce:指数衰减的反弹缓动。
每种算法的easeIn、easeOut 、easeInOut 都会有些微的差异。(视觉效果请参考这里:移动算法动效展示)
颜色过渡
一像素由颜色A变为颜色B。css中有transition或animation,但在canvas中需要js代码来完成。前文讲到,移动动画的本质是坐标(x,y)的变化,而颜色过渡的本质则是rgb(r,g,b)的变化。
该文章《Canvas中颜色过渡动画效果的实现》提供的几种实现思路非常有借鉴意义,尤其是Dom和Canvas结合使用的大思路,可以在很多方面补足Canvas的短板。
1.纯Canvas实现
最纯粹的思路:通过运动算法同时改变(r,g,b)三个值使颜色发生变化。
步骤:
- 确定起始色和终止色:从(0, 0, 255)到(255, 0, 0)
- 确定运动算法,如我们选择匀速运动,则
c*t/d+b
以r值为例,b=0,c=255,t为变量,d=200。
2.Canvas+DOM实现
面对非rgb值时,上述方法就行不通了。
通过window.getComputedStyle()方法可以返回任意DOM的rgb颜色值。
其余步骤不变,我们封装一个函数,将任意形式颜色转换为rgb值:
- 新建一个div
- 将颜色赋给div
- 通过window.getComputedStyle()得到rgb
- 移除div
3.Canvas+DOM+CSS实现
CSS有现成的transition和animation。
我们直接将通过CSS变化后的颜色值传递给Canvas图形重绘。
步骤:
- 新建一个div,并为其设定transition或animation的css
- 通过window.getComputedStyle()获得rgb值,并赋值给context.fillStyle
- 绘制Canvas图形
Canvas本质上是一块空白画布,具备绘图的基本功能,在实现复杂功能,如:动画、交互等时,可能会能力不足。此时,借助DOM往往可以峰回路转。例如,在实现拖拽功能时,一个惯常做法是,创建一个div,绑定鼠标事件,将div位置实时传递给Canvas图形并重绘。