前端开发中,动画实现方式有两种:CSS动画和JS动画,因为渲染方式的不一样,CSS动画相对JS动画性能较好,故优先使用CSS来完成须要的动画效果,可是,在CSS动画没法实现(好比点击网站底部回到顶部)以及须要控制动画暂停、播放、弹跳、倒退或减速等场景下,咱们就得使用JS动画,那如何经过JS编写一个符合天然运动规律、高性能的动画呢?下面,我会经过实现一个完整动画案例来一一展开介绍。css
咱们的目的有两个:前端
符合天然运动规律就是指动画应该符合现实物体运动规律,现实物体是按照必定节奏运动的,并非一成不变的,好比你向空中抛一个球,球飞向空中的速度是先加速而后逐渐减速的,因此咱们的动画应该是有生命力的,可以符合人们对现实现象认知的。git
高性能就是指层如今人们眼睛里的画面无卡顿,画面始终以一个接近恒定的刷新频率(目标是60FPS)进行渲染的。由于根据人眼睛的视觉停留效应,若前一幅画像停留在大脑中的印象还没消失,后一幅画像接踵而至,而且两副画像间的差异很小,就会有“动”的感受,因此咱们的动画的渲染应该维持一个接近恒定的频率,这也是高性能动画的关键。github
在动手实现咱们的实际案例以前,我想而外介绍下高性能动画的关键点。了解浏览器渲染机制的童鞋应该都知道,在浏览器构建完DOM树以及CSSOM以后,就会进入到实际的渲染阶段,渲染通常通过重排、重绘和合成三个阶段。常见的移动元素(left、top等属性),变换元素大小等,都会致使元素从新经历重排和重绘和合成三个阶段,有关对指定的属性设置动画会触发哪一个动做的详细信息,能够查看csstriggers。web
于是,要想动画性能高,咱们就要尽可能减小渲染路径,好比只触发重绘或者合成,从而提升动画性能。好比经过transform
变换元素位置就会只触发合成阶段,于是性能较高。其它可以提高动画性能的方式有:算法
transition
活animation
实现动画(浏览器会有专门的合成器线程处理动画,不影响主线程上的任务)will-change
提早告诉浏览器单独开辟一个线程处理动画transform``opacity
等只触发合成阶段的属性实现动画效果三角函数,学生时代确定学过,是以角度(数学上最经常使用弧度制)为自变量,角度对应任意角终边与单位圆交点坐标或其比值为因变量的函数,在研究三角形和圆等几何形状的性质时有重要做用,也是研究周期性现象的基础数学工具。有点绕,不过我以为只要知道经过它能够获取一组周期性数据,利用这组周期性数据,能够完成周期性动画或者生成周期性曲线便可,后面会有实际例子说明,更多关于三角函数的能够查看这篇文章。浏览器
以正弦曲线为例,正弦曲线公式:y = A sin(Bx + C) + D,其中各个参数的意义以下:wordpress
A 控制振幅,A 值越大,波峰和波谷越大,A 值越小,波峰和波谷越小; B 值会影响周期,B 值越大,那么周期越短,B 值越小,周期越长。 C 值会影响图像左右移动,C 值为正数,图像右移,C 值为负数,图像左移。 D 值控制上下移动。函数
经过调整A、B、C、D值就能够获得咱们想要的曲线效果,这个网站能够可视化查看各类三角函数的曲线效果。工具
缓动函数,区别于匀速运动,缓动函数给咱们提供了随着时间变化按照非匀速变化运动的一种方式,点击这里能够查看各类不一样的缓动曲线,github上流行的tween.js库就是一个具体实现的库。关于缓动函数的更多介绍能够查看如何使用Tween.js各种原生动画运动缓动算法。
缓动函数主要用来调整动画的速率,以下方块从左到右,到底部反弹再回到底部,案例地址
能够看出,缓动函数能使动画看起来更天然而且符合现实运动规律,应该铭记于心的是咱们在处理任何动画时都应该添加缓动效果,而且根据现实世界的一个潜意识规律定义缓动函数,使动画看起来更生动。
普及完基础知识后,咱们来说下咱们须要实现的案例,下面就是咱们须要实现的动画效果,直播工具中常见的点击飘心动画。
这个案例功能很简单,就是点击桃心,随机出现不一样颜色的桃心,以不规则的曲线向上飘动,而后逐渐消失,因为须要控制动画路径以及动态生成动画元素,CSS动画没法实现,故咱们将会采用JS来实现。
首先,咱们须要监听点击事件,生成一个桃心元素,代码以下:
接着,生成的桃心以非直线路径向上飘动,这个路径的生成咱们就可使用三角函数来实现,咱们这里用到了正弦、余弦、正切三种三角函数,分别对应左、中、右三个方向,这三个三角函数的生成返回的值的值域都是[-1,1],配合振幅、偏移量以及元素的基础位置等参数,咱们就能够生成一个相似正弦、余弦、正切的路径曲线。
以正弦曲线为例,生成一个正弦曲线路径的代码以下,其中,deg * Math.PI / 180
为角度转弧度,10表明振幅,注意这里振幅不能太大,不然会超出视图边缘,减2.5表明偏移量,能够自行调整。
生成三条路径曲线的代码:
接下来须要让桃心按照咱们的路径曲线动起来,就须要随时调整元素的位置,首先咱们想到的是使用setTimeout
或者setInterval
,按照1000 / 60 = 16.7ms
间隔时间执行位移函数(FPS为60,平均绘制一帧须要16.7ms),然而因为浏览器中的页面循环系统(Event Loop)的缘由,setTimeout
的回调函数有可能不必定是按照咱们指定的间隔时间执行的(任务队列里面可能掺杂其它微任务),具体缘由读者能够本身去查阅,从而可能会致使动画渲染没法按照规律的刷新频率进行渲染,视觉上看起来就会有卡顿现象。
所以,浏览器提供了requestAnimationFrame
来专门应对这种状况,它的用法等同于setTimeout
,在下一个浏览器刷新周期执行回调函数,只不过每次的间隔时间由浏览器控制,不须要咱们主动定义,于是渲染性能最高,使用js动画通常都是使用这个方法。
另外,动画位置偏移,咱们使用tranform
中的translate
进行位移,而不是使用left
和top
,缘由是translate
只会触发元素从新进入合成阶段,相比使用left
和top
触发重绘、重排,资源消耗更低,于是性能更高。
桃心运动的代码以下:
此时,来看下咱们的动画效果
同时看下性能,很好,FPS锯齿很平整,频率也接近60FPS,表明动画渲染性能较高。
大部分人作到这里估计就结束了,可是回想一下文章一开始说的,咱们的目的是建立一个==高性能且符合天然运动规律==的动画,放到这里就是桃心向上飘动的过程速度应该是先加速而后不断下降的,而不是一成不变的。
故此,引入了缓动函数来调整速率,这里咱们选择了缓出,它开头较快,使动画有反应快速的感受,且结尾有个不错的减速,很是适合咱们的场景,更多缓动动画函数查看easings,这里咱们的目的是调整Y轴方向上速率,代码以下:
最后再看下咱们动画效果,桃心向上飘动先加速后减速,很是天然。
至此,咱们的动画才算完成。
经过这篇文章,我介绍了三角函数和缓动函数在动画中的运用,指出了实现高性能动画的一些关键细节,以及如何去实现符合天然运动规律的动画,虽然个别地方不是很深刻,但但愿个人文章可以给你一个指引,在之后的工做开发中,碰到动画处理更加驾轻就熟,知道该如何实现高效能且符合天然运动规律的动画。
以上完整代码能够在个人codepen查看,另外,访问个人github能够查看个人更多文章。