手抄:浏览器性能优化-硬件加速
一个dom节点对应了一个渲染对象,渲染对象依然维持着dom树的树形结构,渲染对象将知道如何绘制一个dom节点的内容,它通过向一个绘图上下文发出必要的绘制调用来绘制DOM节点
-
渲染层 RenderLayer
处于相同坐标空间(z轴空间)的渲染对象,都将归并到同一个渲染层中,对于满足层叠上下文条件的渲染对象,浏览器会自动为其创建新的渲染层,条件如下:- 根元素
- display不为static的
- opacity < 1
- 有css filter属性
- 有css mask属性
- 有css mix-blend-mode属性且值不为normal
- 有css transform属性且值不为none
- backface-visibility属性不为hidden
- 有css reflection属性
- 有css colunm-count属性且值不为auto或者有css colunm-width属性且值不为auto
- 当前有对opacity、transform、filter、backdrop-filter应用动画
- overflow不为visible
满足以上条件的渲染对象就能拥有独立的渲染层。当然这里的独立是不完全准确的,并不代表着它们完全独享了渲染层,由于不满足上述条件的渲染对象将会与其第一个拥有渲染层的父元素共用同一个渲染层,因此实际上,这些渲染对象会与它的部分子元素共通这个渲染层
-
图形层
处理合成层,将位图作为纹理交付给GPU,GPU将多个位图进行合成,绘制到屏幕上
-
合成层
满足某些特殊条件的渲染层会被浏览器自动提升为合成层。合成层拥有单独的图形层,而其他不是合成层的渲染层,则和其第一个拥有图形层的父层共用一个
条件:
- 3D transforms:translate3d、translateZ等
- video、canvas、iframe等
- 通过Element.animate()实现的opacity动画转换
- 通过css动画实现的opacity动画转换
- position: fixed
- 具有 will-change 属性
- 对 opacity、transform、filter、backdropfilter应用了animation或者transition
- css filter其实并没有效果
-
隐式合成
部分渲染层在特定场景下,会被默认提升为合成层
(一个或多个非合成元素出现在堆叠顺序上的合成元素之上,被提升到合成层)
比如A的z-index比B的z-index大,然后A压在B上,B由于transform被提升为了合成层,浏览器为了不影响视图效果,默认将A也提升成了合成层,于是多了一个合成层
-
层爆炸
多个渲染层被隐式提升为合成层,造成性能问题
-
层压缩
如果多个渲染层和一个合成层发生重叠,则这多个渲染层会压缩到同一个合成层中,虽然有些特定情况下不会进行层压缩,但也一定程度缓解了这个爆炸问题
优化建议:
- 动画使用 transform 实现
- 减少隐式合成
- 减小合成层的尺寸,先设置小一点,然后用scale放大即可