前端动画

前端界面一个很重要的内容就是动画,符合场景的动画不仅可以优化网站页面中的交互细节,提高用户体验,还可以让页面更具有吸引力,给网站带来更多的访问量。通常前端中,实现动画的方案主要有6种:JavaScript直接实现动画,可伸缩矢量图形(Scalable Vector Graphics)动画,CSS3 transition,CSS3 animation,Canvas动画,requestAnimationFrame。

JavaScript直接实现动画

主要是通过JavaScript的setInteral方法来持续调用改变某个元素的CSS样式以达到元素样式持续变化的结果。

通过JavaScript实现动画通常会导致页面频繁性重排重绘,很消耗性能,如果是稍微复杂的动画,在性能较差的浏览器上就会明显感觉到卡顿,所以我们应该尽量避免使用它。

利用seTimeout实现的动画在某些低端机上会出现卡顿、抖动的现象。 这种现象的产生有两个原因:

  1. setTimeout的执行时间并不是确定的。在Javascript中, setTimeout 任务被放进了异步队列中,只有当主线程上的任务执行完以后,才会去检查该队列里的任务是否需要开始执行,因此 setTimeout 的实际执行时间一般要比其设定的时间晚一些。
  2. 刷新频率受屏幕分辨率和屏幕尺寸的影响,因此不同设备的屏幕刷新频率可能会不同,而 setTimeout只能设置一个固定的时间间隔,这个时间不一定和屏幕的刷新时间相同。

demo:

在上面例子中,我们将setInterval的时间间隔设置为16ms,一般认为人眼能识别的流畅动画为每秒60帧,16ms 比 1000ms/16 帧略小一点,这种情况下我们可以认为动画是流畅的。

同理对于需要作节流处理的事件,我们一般也使用 16ms 进行节流处理。

SVG动画

SVG又称可伸缩矢量图形,原生支持一些动画效果,通过组合可以生成较复杂的动画,而且不需要使用JavaScript参与控制。

SVG动画由SVG元素内部的元素属性控制,通常使用以下几个元素:

  • :无动画,常用来实现延时操作
  • :单属性动画,修改元素的一个属性。
  • :颜色动画,已废弃,可使用替代
  • :变换动画,同CSS3 的transform 常见的有rotate, skew, scale, translate等
  • : 使元素按照指定的路径移动,path 属性就是SVG图形中的path,常见的属性有:

    • M = moveto
    • L = lineto
    • H = horizontal lineto
    • V = vertical lineto
    • C = curveto
    • S = smooth curveto
    • Q = quadratic Belzier curve
    • T = smooth quadratic Belzier curveto
    • A = elliptical Arc
    • Z = closepath

      大写表示绝对定位,小写表示相对定位

demo:

SVG的一大优势是含有较为丰富的动画功能,原生绘制各种图形、滤镜和动画,并且能被js调用。但是,另一方面元素较多且复杂的动画使用svg渲染会比较慢,而且SVG格式的动画绘制方式必须让内容嵌入到HTML中使用。CSS3的出现让svg的应用变得相对少了。

CSS3 transition

transition是过度动画。但是transition并不能实现独立的动画,只能在某个标签元素样式或状态改变时进行平滑的动画效果过渡,而不是马上改变。

我们一般通过改变元素的起始状态,让元素的属性自动进行平滑过度产生动画,但不能应用于处理元素独立动画的情况,而是需要不断改变元素的属性值来持续触发动画过程。

demo:

在移动端开发中,直接使用transition动画会让页面变慢甚至卡顿。所以我们通常添加transform:translate3D(0,0,0)或transform:translateZ(0)来开启移动端动画的GPU加速,让动画过程更加流畅。

CSS3 animation

animation 算是真正意义上的CSS3动画。通过对关键帧和循环次数的控制,页面标签元素会根据设定好的样式改变进行平滑过渡。而且关键帧状态的控制是通过百分比来控制的。

demo:

CSS3最大的优势是摆脱了JavaScript的控制,并且能利用硬件加速以及实现复杂动画效果。

Canvas动画

canvas作为H5新增元素,是借助Web API来实现动画的。

Canvas动画和SVG动画的主要区别是,SVG动画是通过SVG元素内部的配置规则来实现的,而Canvas是通过Javacript API来实现的。

通过getContext()获取元素的绘制对象,通过clearRect不断清空画布并在新的位置上使用fillStyle绘制新矩形内容实现页面动画效果。

demo:

使用Canvas的优势是可以应对页面中多个动画元素渲染比较慢的情况,完全通过JavaScript来控制渲染动画的执行,这就避免了DOM性能较慢的问题,可用于实现较复杂动画。

requestAnimationFrame

requestAnimationFrame是另一种Web API,原理与setTimeout和setInterval类似,都是通过javascript持续循环的方法调用来触发动画动作。但是requestAnimationFrame是浏览器针对动画专门优化形成的APi,在性能上比另两者要好。

requestAnimationFrame的方式的优势如下:

  1. 经过浏览器优化,动画更流畅
  2. 窗口没激活时,动画将停止,省计算资源
  3. 更省电,尤其是对移动终端

浏览器优化是指由系统来决定回调函数的执行时机。具体一点讲,如果屏幕刷新率是60Hz,那么回调函数就每16.7ms被执行一次,如果刷新率是75Hz,那么这个时间间隔就变成了1000/75=13.3ms,换句话说就是,requestAnimationFrame的步伐跟着系统的刷新步伐走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。

参考资料