为什么Chrome不需要在更改时重新绘制整个图层?

Dim*_*nis 19 css browser google-chrome repaint google-chrome-devtools

我试图在实践中理解Chrome的布局→绘图→复合管道是如何工作的.在我的测试中,我对Chrome在以下情况下的行为感到困惑.(Codepen)

var button = document.querySelector('button');
var red = document.querySelector('.red');
var blue = document.querySelector('.blue');
button.addEventListener('click', function() {
  red.classList.toggle('test');
})
Run Code Online (Sandbox Code Playgroud)
.wrapper {
  height: 100%;
  width: 100%;
  background-color: teal;
  position: static;
}

.square {
  height: 200px;
  width: 200px;
  position: static;
  transition: transform 0.3s ease,
    opacity 0.3s ease,
    width 0.3s ease,
    height 0.3s ease,
    box-shadow 0.3s ease;
}

.red {
  /* position: absolute; */
  background-color: red;
  top: 100px;
  left: 100px;
  /* will-change: transform; */
  opacity: 1;
}

.blue {
  background-color: blue;
  z-index: 3;
}

.test {
  /* transform: translate3d(50px, 50px, 0); */
  /* opacity: 0; */
  width: 60px;
  height: 60px;
  /* box-shadow: 0px 0px 0px 10px rgba(0,0,0,.5) */
}

button {
  position: fixed;
  right: 100px;
  top: 50px;
  z-index: 10000;
  font-weight: bold;
  background-color: yellow;
  padding: 5px 10px;
  /* will-change: transform; */
}
Run Code Online (Sandbox Code Playgroud)
<div class="wrapper">
  <div class="red square"></div>
  <div class="blue square"></div>
</div>
<button>Click</button>
Run Code Online (Sandbox Code Playgroud)

重现.

  • 使用Chrome;
  • 打开高亮重画上,在开发工具;
  • 打开" 图层"面板;
  • 单击黄色按钮切换红色方块的大小;
  • 看看突出显示为"重新绘制"的内容,以及当前的图层;
  • 在改变position红色方块之后尝试这样做.

我们在包装元素中有两个正方形,一个是红色,另一个是蓝色.在Chrome的" 图层"面板中,整个内容显示为一个图层.

  • 如果两个方块都被static定位,当我转换红色的宽度和高度时,我可以看到整个层被重新绘制,这对我来说是有意义的,因为,如果所有3个元素都在同一层中,则更改尺寸为1,改变整个图层的最终结果,因此整个图层必须重新绘制.

  • 如果我将红色方块设置为absolute定位(您可以通过取消注释.red样式规则中的线条来实现),当我转换其宽度和高度时,即使开发工具仍显示一个图层,只有该图层内的红色正方形,显示为重新绘制.

题.
第二种情况对我没有意义.

如果两个正方形和包装元素都在同一层中,那么不应该更改一个元素会影响整个图层并导致整个图层重新绘制,而不仅仅是红色正方形?

其他问题.
在布局阶段(或确定图层的任何阶段),Chrome是否会将某些元素分离到各自的图层中(position例如,由于属性)?这是为什么它能够分开重绘它们?在合成阶段之后,它是否会转储它们,因此开发人员只能在开发工具中看到一个图层?

相关背景.
我对现代浏览器绘画过程的粗略理解如下:

  • 在布局阶段,浏览器将CSS与HTML信息结合起来,以便在屏幕上找出视觉元素的位置和尺寸.我也相信这是确定有多少渲染层的时间(will-change例如).
  • 在绘制阶段,浏览器为每个图层创建一个帧缓冲区,其中包含有关每个像素应显示的颜色的信息,具体取决于布局数据.
  • 在合成阶段,GPU根据绘画阶段生成的数据将所有图层合成在一起,并将最终结果发送到屏幕.

Dim*_*nis 15

所以,这里令人困惑的一点是,开发工具的Paint闪烁只会闪现从前一帧中失效的图层部分(因此,如果一个absolute定位的正方形开始变小,则帧之间的无效区域就是一个区域具有正方形在前一帧中的尺寸和坐标)

但是,无论帧之间的无效部分有多大或多小,整个层内部都会重新绘制.

因此,例如,闪烁光标在Paint Flashing上看起来很小,但实际上整个图层需要重新绘制.

实际上,如果我们打开" 性能"面板并启用" 高级绘画仪器"选项,我们可以看到在方形过渡之间,整个层在问题中描述的两种场景中都会被绘制.

Chrome Paint分析1

Chrome Paint分析2

来源

自由软件
网址:https :
//twitter.com/paul_irish/status/971196996924030977 https://twitter.com/paul_irish/status

一些观察

如果我们要尽量减少布局和绘制步骤以尽可能少地进行操作,我们应该将红色方块和黄色按钮分开到它们自己的渲染层.

这种方式与按钮交互并调整正方形大小只会影响它们各自的图层,并且不会重新绘制背景图层(包括背景和蓝色方块).

  • 我已经和他联系了.由于无法保证他实际上会自己发布答案,因此现在必须这样做. (6认同)