【降维打击】Layers

497 阅读4分钟
    /**
        @date 2021-12-05 【降维打击】Layers
        @description 关于图层
    */

壹(序)

或许从题目中,并不知道我这篇文章想要讲的是什么,那么你可以打开Chrome的控制台,找到Layers部分(没有的话去点击控制台右上角的三个点,选择More tools,点击Layers)。

然后观察:

  • 中间上面部分其实就是这篇文章,以及一些操作按钮(可以尝试去点一点)
  • 左边是当前页面存在的Layers
  • 下面是一些数据

layers.png

贰(Node and DOM Tree)

我们知道,浏览器在渲染最初就是解析得到的HTML文件,然后解析出相应的DOM Tree,其中DOM Tree中有很多Node,而往后如何渲染,就是今天想要讲述的东西,就涉及到渲染里面很重要的一个面--layer。

叁(RenderTree)

在开始讲解layer之前,我们还需要理解一个东西,渲染树(RenderTree),RenderTree其实与DOM Tree是相互映射的,从DOM Tree中的 HMTL 元素我们可以解析出相应的RenderObject,RenderObject也就是每个DOM Node应该怎么渲染(如何渲染,在何处渲染),而RenderObject就组成了RenderTree。

由此我们知道:

DOM Tree => RenderObject => RenderTree

而且:DOM Tree 与 RenderTree 是 1对1

话不多说,画图:

DOMTree-RenderTree.jpg

肆(RenderLayer)

最上层的RenderObject一定会对应一个RenderLayer,之后的每个RenderObject都会与一个RenderLayer相关联,如果没有相对应的RenderLayer,那么就匹配祖先RenderObject对应的RenderLayer,所以这两者的映射关系应该是多对一。

继续画图:

RenderTree-RenderLayers.jpg

那么RenderLayer是什么呢?

首先,最上层(不是指空间上的上层)的RenderLayer就是由Document生成的RenderObject再生成的,也就是祖先RenderLayer,在简单的页面中,可以就只有这一个RenderLayer;

其次,RenderLayer,就是渲染图层,我们知道整个页面是由一个个的HTML元素组成的,那么最初的RenderLayer,就可以看作是最下面的那个图层,如果我们对于一些元素可以生成相应的图层的话,是不是更好管理,更好渲染呢,所以会给我们相应的条件,触发了这些条件就能够另外起一个图层,用于特殊的处理,比如使用canvas时,可能会涉及到很快速很经常的渲染,那么就能把这个canvas单独起一个图层,渲染canvas的时候只渲染canvas而不会去渲染其他部分,这能提升很多渲染性能。

那么如何另起图层?

有以下方法:

  • 定位:position 为 relative, absolute
  • 使用transform
  • 使用overflow
  • 透明层
  • canvas
  • video

伍(GraphicsLayer)

还记得一开始让你打开控制台的Layers tool吗?

这就是GraphicsLayer:图形层。

随着时代的发展,我们不仅仅只依靠CPU去做处理了,在图形上,我们更应该使用GPU去做处理,这是更合理,更快的渲染方法,GraphicsLayer就是可以使用GPU做渲染的图层,与RenderLayer也是一个多对一的关系。

还是画图:

RenderLayers-GraphicsLayers.jpg

可以看到,GraphicsLayer就是在RenderLayer的基础上起的,同样的RenderLayer顶层图层对应相应的GraphicsLayer顶层图层,RenderLayer子孙图层如果有相应的GraphicsLayer图层则匹配,没有的话就是顶层RenderLayer图层,也是一个多对一的映射关系。

同时,GraphicsLayer也是用于渲染的图层,但是会更高效,同样的,对于一些需要快速渲染的部分,我们可以给它起一个GraphicsLayer,在渲染时就只会渲染这一个图层,提升渲染性能。

是不是感觉我们可以利用这个知识做些什么?没错,就是重绘重排,重绘重排的最小单位就是Layer,所以将游戏需要经常重绘重排的组件,放置在单独的图层里,可以减少重绘重排带来的不良影响,当然,切记不可贪多!

最重要的,如何另起一个GraphicsLayer?

  • canvas
  • video
  • transition
  • transform: translateZ(0);
  • will-change: transform;

陆(跋)

最终我们可以得到这样一张图:

从图可以看到DOM Tree、RenderTree、RenderLayers以及GraphicsLayers之间的映射关系。

process.jpg

最重要的,我们对底层的渲染有了更进一步的理解,而不仅仅只能说一句从DOM树再到渲染树balabala,我们到渲染树还能更加深入!