浅析Css中动画优化原理

说到web前端开发,就不得不提到动画,动画是网站吸引用户的重要因素之一。
动画的实现一般有2种实现方式,通常说是命令式动画和声明式动画:
命令式动画:用JavaScript实现,优点是富有可操控性如暂停,取消等,缺点是占用JS主线程,可能会丢失帧。
声明式动画:用css实现,优点是浏览器会对动画进行优化,缺点是缺乏可操控性。

重点说下声明式动画,浏览器对动画的优化,如我们所知:在对DOM中的element进行动画时,尽量使用transform、opacity属性和will-change属性(实验中),如下:
位置的变化: transform:translate(x,y)
大小的变化: transform: scale(x)
角度的变化: transform:rotate(n)
透明度的变化: opacity:0~1
即将变化的属性:will-change: attr

为何使用这些属性动画性能就能得到优化?原因是因为GPU加速合成(GPU Accelerated Compositing),
那么,什么是GPU? 为何GPU可以加速? Composite是什么?下面一一来解答。

GPU:图形处理器(Graphics Processing Unit),是显卡的核心,相当于CPU在计算机中的作用,由于GPU的核数多而缓存小,所以适合做海量数据的简单运算,而CPU则擅长计算比较复杂的任务逻辑。

为何GPU可以加速?
当CPU把图形绘制的任务分配给了GPU,则CPU可以去做其他的任务,同时GPU专心的绘制图像,从而实现并行操作,提高渲染效率, 同时GPU对涉及大量像素处理的绘制和合成操作有做专门的设计,所以要比CPU有效率。

合成(Composite):

一般简单来说,浏览器渲染过程经过如下几个步骤,可以看出渲染层合成(Composite)是在绘制之后,屏幕展示之前。
那么为什么要形成合成层呢?简单介绍下浏览器渲染的原理。


如图所示,

  1. 在一个HTML中,每一个Element有一个对应的DOM Node存在;
  2. 在DOM tree 中每个node节点都有一个LayoutObject 对应存在,LayoutObject 的作用是知道如何渲染它所对应的Dom Node;
  3. 多个LayoutObject 可能对应一个PaintLayer,一般拥有同一坐标空间的LayoutObject 属于同一个RenderLayer,或者与它的第一个拥有PaintLayer的祖先的LayoutObject 创建的PaintLayer拥有同一个。PaintLayer包含2个数组,包括当前层之上和之下的PaintLayer。PaintLayer的作用是使得网页的元素渲染能有正确的顺序和效果;
  4. 多个PaintLayer可能对应一个GraphicsLayer 。一些特殊的PaintLayer会被认为是合成层(composite),其中的一个原因就是前面诉说的对DOM元素动画使用了transform等属性,合成层(composite)单独拥有一个GraphicsLayer ,而其他的PaintLayer则和第一个拥有GraphicsLayer的祖先的PaintLayer创建的GraphicsLayer拥有同一个,GraphicsLayer的作用是作为纹理(texture)上传给 GPU ,然后由GPU绘画到屏幕上。

在传统的渲染方式中,整个网页只有一个GraphicsLayer,任何一个Layer的内容更新都会引起相关所有层的重绘,那么这些都将造成CPU很大的负担。所以有了上面诉说的GPU加速合成即硬件渲染模式,利用合成器渲染,合成器跟踪最近一次被绘制后有变化的GraphicsLayer,只更新有变化的GraphicsLayer相对的texture,进而通过GPU 进程直接绘制到窗口上。

参考:
https://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
http://taobaofed.org/blog/2016/04/25/performance-composite/


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!