浏览器渲染流程

要优化动画性能,首先要了解浏览器是如何进行元素渲染的,浏览器的渲染流程有以下三步

  1. 计算元素的样式(可能通过脚本重新计算)
  2. 生成每个元素的几何形状和位置(布局)
  3. 绘制图层的每个像素(初始化绘图并且进行绘图),将图层绘制到屏幕上(图层的合成

举个例子,我们如果改变一个正常文档流的元素的 width 属性,由于元素之间的相互影响,就会导致文档树布局重新计算,排版和绘制

为了使动画更加流程,就要减少浏览器的绘制工作,简单的说就是减少重排重绘

transform属性

transform 属性可以向元素应用 2D 或者 3D 转换,可以对元素进行选择,缩放,移动和倾斜

2D 变换一般使用的有 translate,scale,rotate,skew,在前端的性能优化上,我们要避免浏览器做过多的重绘和重排,transform 可以在一定程度上优化动画效果。

left/top vs transform

在日常中我们可以使用 left/top 或者 transform 来实现元素的位移,虽然效果是一样的,但是其实性能上还是有一定影响的,比如下面的例子

上面的例子使用 left/top 来实现元素的位移效果,经过 chorme 的性能分析,可以看出浏览器对该动画的处理大量使用GPU的计算,开启多个栅格化绘制线程绘制,复合层的合成来完成,界面明显看出卡顿。再看下面的例子

第二种使用 transform 来实现同样的效果,可以看出浏览器会单纯使用 GPU 加速来完成整个动画,性能大大提高,这是因为 transform 会创建一个新的渲染层来计算并应用元素的变化(trasnlate/scale/opacity)

实现动画注意事项

  • 尽量使用 css keyframes 结合 transform 来实现
  • 写 Javascript 动画时,使用 requestAnimationFrame,避免使用 setTimeoutsetInterval
  • 避免直接修改元素的 style 属性来实现动画,例如 jquery.animate,可以使用 css,例如 animate.css
  • 使用 translate 来替代 left/topscale 来替代 width/height
  • 使用 translateZ(0) 或者 translate3d(0,0,0) 来强制创建一个图层
  • 移动端浏览器可以使用3d变换来开启gpu加速,但是要适量,太多反而会降低性能,耗电