变换/不透明属性是否调用浏览器传送带中的绘制步骤

在调查浏览器的呈现工作原理时,我注意到,在启用了标志的Chrome开发工具中,paint flashing触发器在更改transform/opacity属性时会触发绘制步骤。

查看这些带有代码的屏幕截图:

示例1(transform/opacity属性)

let elem = document.querySelector(".newLayer");
let count = 0;
function anim(){
  elem.style.transform = `translate(${count}px,0)`;
  /// interchangeable
  /// elem.style.opacity = `${count/500}`;
  if(count++ < 500)
    requestAnimationFrame(anim);
  }
anim();
.newLayer{
  position:relative;
  width:150px;
  height:150px;
  background-color: red;
}
<div class="newLayer">I am a new Layer</div>

示例2(transform/opacity具有will-change的属性)

let elem = document.querySelector(".newLayer");
let count = 0;
function anim(){
  elem.style.transform = `translate(${count}px,0)`;
  /// interchangeable
  /// elem.style.opacity = `${count/500}`;
  if(count++ < 500)
    requestAnimationFrame(anim);
  }
anim();
.newLayer{
  will-change: transform;
  position:relative;
  width:150px;
  height:150px;
  background-color: red;
}
<div class="newLayer">I am a new Layer</div>

它把我搞糊涂了,因为我看过this one和this one来源,他们说当您使用transform/opacity时,忽略了绘制阶段。那是什么呢?为什么我们在第一个例子中看到了油漆,而在第二个例子中没有呢?哪一个在撒谎?


有趣的一个包含2个绘制操作的示例:

let elem = document.querySelector(".newLayer");
let count = 0;
function anim(){
  elem.style.left = `${count}px`;
  if(count++ < 500)
    requestAnimationFrame(anim);
  }
anim();
.newLayer{
  position:relative;
  width:150px;
  height:150px;
  background-color: red;
}
<div class="newLayer">I am a new Layer</div>

是的,有定位的Used属性,但请看绘制操作,一个大条纹和一个小条纹,如没有will-change的示例。这是什么意思(我说的是细小条纹长度的油漆)?

小漆挡路跟栅格线有关吗,大的呢?


解决方案

两个示例都没有说谎。

浏览器最大限度地减少了合成所需的层数。它只有在有理由相信会有好处的情况下才会创建一个层。

如果您使用CSS过渡、CSS动画或Web动画设置变换或不透明度动画,浏览器会提前知道元素正在以一种可能通过创建层进行优化的方式进行动画制作,因此Chrome会在动画持续时间内创建一个动画。

如果使用RAF设置动画,浏览器就没有这种预见性。will-change作为一种提示浏览器应根据更改的属性为此元素创建层的方式而存在。

这些都是提示,并不保证浏览器会创建层。有些浏览器还会在其他情况下创建层,例如当另一个元素需要在层上绘制时,以及在其他一些CSS(如transform: translateZ(…))的情况下。

相关文章