# 简述渲染中的分层与合成
本文将简述浏览器渲染过程中的分层过程
# 渲染层合成
在经过 HTML 解析、样式计算和布局之后,我们会得到一颗布局树。布局树上的每一个节点都是一个渲染对象(Render Object)。当多个渲染对象处于同一个 Z 轴空间的时候,就会形成一个渲染层(Render Layers)。一个渲染层中存在多个渲染对象,通常一个页面会被分为多个不同的渲染层,以体现他们的层叠关系。
对于满足形成层叠上下文条件的渲染对象,浏览器会自动为其创建新的渲染层。比如:
- 根元素 document
- 非 static 的定位
- 添加了 transform 属性,且取值不为 none
- 添加了 overflow 属性,且取值不为 visible
满足上述任一条件的元素,会被分配到一个新的渲染层。不满足条件的元素,和其第一个拥有渲染层的祖先元素共用一个渲染层。
# 图形层
图形层(Graphics Layer)也可以简称为图层。分层的最终结果就是将页面分为了多个图形层,图形层负责生成最终准备呈现的内容图形。图形层会将本层的位图交给 GPU 进行最终的页面渲染。
图形层只能处理合成层,而不能直接处理渲染层。
# 合成层
满足某些条件的渲染层,会被浏览器自动提升为合成层。每个合成层都单独拥有一个图形层,其他没有被提升为合成层的渲染层会和第一个拥有图形层的父层共享一个图形层。
是否提升为合成层是依据浏览器的分层策略决定的,我们无法指定让浏览器为哪一个元素分层,但是我们可以通过设置 CSS 属性,来影响浏览器的分层结果,下面这些属性都可能影响浏览器的分层结果,从而使得浏览器将这个元素对应的渲染层提升为合成层:
- 具有 will-change 属性
- 3D 变换 transforms:translate3d、translateZ 等
- position: fixed
其中最常用的,也是分层成功率最高的,就是 will-change 属性。
# 合成层的优势
由于合成层的图像会单独具有一个图形层,所以处于合成层中的元素发生重绘和重排,不会影响其他层中的元素。
当元素提升为合成层后,transform 和 opacity 不会触发 repaint,如果不是合成层,则其依然会触发 repaint。
另外,合成层的图像绘制是交给 GPU 来进行处理的(GPU 加速),GPU 的计算速度更快,且不会影响 CPU 中的线程。而渲染层的图像渲染是 CPU 处理的,速度更慢。
# 参考资料
网络上关于这部分的资料十分有限,所以暂时无法深入探讨具体过程,本文参考了以下文章: