浏览器渲染流程(下) 分层、绘制、合成

浏览器渲染流程(下) 分层、绘制、合成

前言

上一篇讲了一点非常普遍的部分,可能很常听别人说(虽然重绘部分还没讲)。

这一篇会讲点相对来说较少听到过的,如分层、光栅化、合成。

渲染流程

4. 分层(Layer)

因为页面中有很多复杂的效果,像是3D变换,页面滚动等,为了更方便的实现这些效果,渲染引擎回味特定的节点生成专用的图层,并生成一颗对应的图层树,最后再合成图层。

怎么查看页面的分层情况呢?

浏览器渲染流程(下) 分层、绘制、合成

按上图操作即可。

浏览器渲染流程(下) 分层、绘制、合成

每一个黑框都是一个图层。

那么需要满足什么条件,渲染引擎才会为特定的节点创建新的图层呢?

  1. 拥有层叠上下文[1]属性的元素会被提升为单独的一层

    <style>
        .bottom {
          position: fixed;
          width100px;
          height100px;
          background-color: pink;
        }

        .top {
          position: absolute;
          width50px;
          height50px;
          background-color: purple;
          z-index1;
        }
    </style>

    <body>
      <span class="bottom"></span>
      <span class="top"></span>
    </body>
    浏览器渲染流程(下) 分层、绘制、合成
  2. 需要裁剪的地方也会被创建为图层

    这里的剪裁就是,当内容超过容器体积时,对文字进行裁剪。overflow:hidden不会创建新的图层color{red}overflow: hidden不会创建新的图层overflow:hidden不会创建新的图层。

    <style>
        .clip {
          width100px;
          height100px;
          background-color: pink;
          overflow: auto;
        }
    </style>

    <body>
      <div class="clip">
        <p>123456789123</p>
        <p>123456789123</p>
        <p>123456789123</p>
        <p>123456789123</p>
      </div>
    </body>
    浏览器渲染流程(下) 分层、绘制、合成

出现要裁剪的时候,渲染引擎回为文字部分当都创建一个图层。滚动条也会是一个图层。(包括上下、左右两条滚动条)

5. 绘制(Paint)

分层结束后,我们会得到图层树,然后渲染引擎就会对图层树上的每个图层进行绘制。

而绘制的过程就是模仿画画,会把涂层的绘制拆分成很多个绘画指令。我们想要绘制只需要依次执行一个绘制列表的每一条指令即可,比如,画一个矩形,画一个边框等。

那么怎么查看绘制的指令呢?

打开Layer面板,按下图步骤操作。

浏览器渲染流程(下) 分层、绘制、合成
浏览器渲染流程(下) 分层、绘制、合成

可以发现,绘制指令还会包括两部分:

  • rect:绘制的范围。如果是其他形状可能不是rect,而是rrect之类。

  • paint:绘制的一些样式,包括是填充还是线这种

6. 合成

6.1 光栅化(Raster)

上一步(绘制)中,我们看到了绘制指令列表。但是实际的绘制操作并不是主线程来完成的,而是合成线程来完成的。

渲染进程中主线程和合成线程的关系如下图所示:

浏览器渲染流程(下) 分层、绘制、合成

当图层的绘制指令列表准备好之后,主线程会把该列表提交(commit)给合成线程。然后合成线程开始工作:

  1. 合成线程将图层划分为图块(tile)

  2. 图块栅格化

**合成线程将图层划分为图块(tile)**:

通常一个页面会很大(长),但是用户只能看到其中一部分,而这一部分叫做视口(viewport)。有一些图层也会很大,但是用户只能通过视口看到一部分,所以就没必要将整个图层都绘制出来。这就是将图层划分成图块的原因。

浏览器渲染流程(下) 分层、绘制、合成

图块栅格化:将图块转换为位图。(会优先将视口附近的图块先转换为位图)

渲染进程维护了一个栅格化的线程池,所有的图块栅格化都是在线程池内执行的。而且栅格化过程中会使用GPU来加速生成位图,使用GPU生成位图的过程叫做快速栅格化,生成的位图会保存在GPU内存中。

浏览器渲染流程(下) 分层、绘制、合成

6.2 合成(Composite)与显示

当所有的图块都被光栅化后,合成线程就会生成一个绘制图块的命令(DrawQuad),然后将该命令提交给浏览器进程。浏览器进程中的组件viz会根据该命令,将页面内容绘制到内存中,最后将页面内容从内存中拿出来,显示在屏幕上。

合成操作是在合成线程上完成的,也就是说,执行合成操作时,是不会影响到主线程的。

7. 完整流程

浏览器渲染流程(下) 分层、绘制、合成

回流、重绘、合成

回流(Reflow)

回流需要重新根据CSSOM和DOM来计算布局树,然后完整执行渲染流水线,包括分层、绘制、合成(光栅化)。

回流也叫重排

浏览器渲染流程(下) 分层、绘制、合成

从上图也可以看出来,回流需要完整执行渲染流水线,所以开销也是最大的。

会导致回流的操作(以及减少回流的方法)

  1. DOM的增删行为:如果需要大量增删子元素,最好使用DocumentFragment文档碎片来减少回流

  2. 几何属性的变化:如果需要修改多个属性,例如同时修改宽高、字体大小等,可以将这些定义在一个class里,这样就只会引起一次回流。

  3. 元素位移操作:使用transform代替top等位移操作。因为transform会开启硬件加速(GPU加速),后面合成小节会讲到。

  4. 获取元素的偏移量属性:获取color{red}获取获取offsetTopscrollTopclientTopoffsetWidth等属性,因为浏览器为了确保值得正确性,所以即使只是获取属性值也会引起回流。少获取元素偏移量属性。如果要获取偏移量属性而且是多次操作,最好做下缓存

  5. 浏览器窗口尺寸改变

  6. 初始渲染

重绘(Repaint)

如果修改元素的背景颜色,不会触发布局、分层阶段,直接进入绘制阶段,然后执行之后的子阶段,这个过程就叫重绘。

浏览器渲染流程(下) 分层、绘制、合成

重绘不会触发布局、分层阶段,所以效率比起回流要高很多。

合成

如果使用CSStransform来实现动画效果,会跳过布局和绘制阶段,直接在非主线程进行合成动画。合成的效率比回流、重绘要高很多,因为合成是在非主线程进行合成,还跳过了布局和绘制阶段。

浏览器渲染流程(下) 分层、绘制、合成

可以在CSS Triggers[2]查看,那些属性会触发回流、重绘、合成。有一些属性还会因为内核不同,触发的也不同。

参考

技术淘金丨浏览器渲染流程[3]

浏览器原理4:页面渲染 – 简书[4]

参考资料

[1]

https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context: https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context

[2]

https://csstriggers.com/: https://csstriggers.com/

[3]

http://forum.microapp.bytedance.com/mini-app/posts/626a148306b7b66d55cf8bcb: http://forum.microapp.bytedance.com/mini-app/posts/626a148306b7b66d55cf8bcb

[4]

https://www.jianshu.com/p/85064431de38: https://www.jianshu.com/p/85064431de38


原文始发于微信公众号(赤蓝紫):浏览器渲染流程(下) 分层、绘制、合成

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/45078.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!