浏览器渲染流程
要优化动画性能,首先要了解浏览器是如何进行元素渲染的,浏览器的渲染流程有以下三步
- 计算元素的样式(可能通过脚本重新计算)
- 生成每个元素的几何形状和位置(布局)
- 绘制图层的每个像素(初始化绘图并且进行绘图),将图层绘制到屏幕上(图层的合成)
举个例子,我们如果改变一个正常文档流的元素的 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
,避免使用setTimeout
和setInterval
- 避免直接修改元素的 style 属性来实现动画,例如
jquery.animate
,可以使用 css,例如animate.css
- 使用
translate
来替代left/top
,scale
来替代width/height
- 使用
translateZ(0)
或者translate3d(0,0,0)
来强制创建一个图层 - 移动端浏览器可以使用3d变换来开启gpu加速,但是要适量,太多反而会降低性能,耗电