# 渲染层合成
DOM树种每个节点都会有一个渲染对象,当它们的渲染对象处于相同的坐标空间(z轴层面)上,就会形成一个 RenderLayers
,也就是渲染层。渲染层将保证页面元素以正确的顺序堆叠,这时候就会出现渲染层合成,从而正确处理透明元素和重叠元素的显示。
# 浏览器的渲染原理
2、渲染层(RenderLayer) 这是浏览器渲染期间构建的第一个层模型,处于相同坐标空间(z轴空间)的渲染对象,都将归并到同一个渲染层中,因此根据层叠上下文,不同坐标空间的的渲染对象将形成多个渲染层,以体现它们的层叠关系。所以,对于满足形成层叠上下文条件的渲染对象,浏览器会自动为其创建新的渲染层。能够导致浏览器为其创建新的渲染层的,包括以下几类常见的情况:
根元素 document
有明确的定位属性(relative、fixed、sticky、absolute)
opacity < 1
有 CSS fliter 属性
有 CSS mask 属性
有 CSS mix-blend-mode 属性且值不为 normal
有 CSS transform 属性且值不为 none
backface-visibility 属性为 hidden
有 CSS reflection 属性
有 CSS column-count 属性且值不为 auto或者有 CSS column-width 属性且值不为 auto
当前有对于 opacity、transform、fliter、backdrop-filter 应用动画
overflow 不为 visible
DOM 节点和渲染对象是一一对应的,满足以上条件的渲染对象就能拥有独立的渲染层。当然这里的独立是不完全准确的,并不代表着它们完全独享了渲染层,由于不满足上述条件的渲染对象将会与其第一个拥有渲染层的父元素共用同一个渲染层,因此实际上,这些渲染对象会与它的部分子元素共用这个渲染层。
3、图形层(GraphicsLayer) GraphicsLayer 其实是一个负责生成最终准备呈现的内容图形的层模型,它拥有一个图形上下文(GraphicsContext),GraphicsContext 会负责输出该层的位图。存储在共享内存中的位图将作为纹理上传到 GPU,最后由 GPU 将多个位图进行合成,然后绘制到屏幕上,此时,我们的页面也就展现到了屏幕上。 所以 GraphicsLayer 是一个重要的渲染载体和工具,但它并不直接处理渲染层,而是处理合成层。
4、合成层(CompositingLayer) 满足某些特殊条件的渲染层,会被浏览器自动提升为合成层。合成层拥有单独的 GraphicsLayer,而其他不是合成层的渲染层,则和其第一个拥有 GraphicsLayer 的父层共用一个。 那么一个渲染层满足哪些特殊条件时,才能被提升为合成层呢?这里列举了一些常见的情况:
3D transforms:translate3d、translateZ 等
video、canvas、iframe 等元素
通过 Element.animate() 实现的 opacity 动画转换
通过 СSS 动画实现的 opacity 动画转换
position: fixed
具有 will-change 属性
对 opacity、transform、fliter、backdropfilter 应用了 animation 或者 transition
因此,文首例子的解决方案,其实就是利用 will-change 属性,将 CPU 消耗高的渲染元素提升为一个新的合成层,才能开启 GPU 加速的,因此你也可以使用 transform: translateZ(0) 来解决这个问题。 这里值得注意的是,不少人会将这些合成层的条件和渲染层产生的条件混淆,这两种条件发生在两个不同的层处理环节,是完全不一样的。 另外,有些文章会把 CSS Filter 也列为影响 Composite 的因素之一,然而我验证后发现并没有效果。