降低绘制的复杂性并减少绘制区域

绘制是填充像素的过程,像素最终合成为用户的屏幕。它往往是流水线中所有任务中运行时间最长的任务,应尽可能避免此任务。

Paul Lewis

绘制是填充像素的过程,像素最终合成 用户的屏幕。它往往是集群内运行时间最长的任务 以及尽可能避免的流水线。

摘要

  • 除 transform 或 opacity 属性之外,更改任何属性始终都会触发绘制。
  • 绘制通常是像素管道中开销最大的部分;请尽可能避免
  • 通过层的提升和动画的编排来减少绘制区域。
  • 使用 Chrome DevTools 绘制分析器评估绘制的复杂性和开销;尽可能减少

触发布局和绘制

如果您触发布局,则系统始终都会触发绘制,因为更改任何元素的几何图形意味着其像素需要修正!

完整的像素管道。

如果更改非几何图形属性(如背景、文本颜色或阴影),也会触发绘制。在这些情况下,不需要布局,并且流水线将如下所示:

无布局的像素管道。

使用 Chrome 开发者工具快速识别绘制瓶颈

您可以使用 Chrome 开发者工具快速识别正在绘制的区域。打开“渲染”标签页 然后启用 Paint Flashing

开启此选项后,每当发生绘制操作时,Chrome 都会让屏幕闪烁绿光。如果您看到整个屏幕闪烁绿色,或者看到您不认为应该绘制的屏幕区域,则应该进一步挖掘。

每次发生绘制时网页闪烁绿色。

提升移动或淡出的元素

绘制并非总是绘制到内存中的单个图像。事实上,如有必要,浏览器可以绘制到多个图像或合成器层。

合成器层的表示形式。

这种方法的优势在于,定期重绘或使用变形在屏幕上移动的元素,可以在不影响其他元素的情况下进行处理。这与 Sketch、GIMP 或 Photoshop 等艺术软件包相同,在 Sketch、GIMP 或 Photoshop 等艺术软件包中,可以处理各个图层并进行相互合成,以创建最终图像。

创建新图层的最佳方法是使用 will-change CSS 属性。这适用于 Chrome、Opera 和 Firefox,并且如果值为 transform,则会创建一个新的合成器层:

.moving-element {
  will-change: transform;
}

对于不支持 will-change 但受益于图层创建的浏览器(例如 Safari 和 Mobile Safari),您需要(滥用)使用 3D 转换来强制创建新图层:

.moving-element {
  transform: translateZ(0);
}

但必须小心,不要创建过多的层,因为每一层都需要内存和管理开销。如需了解详情,请参阅坚持仅合成器的属性和管理层计数部分。

如果您已将某个元素提升到新层,请使用开发者工具确认这样做是否为您带来了性能优势。请勿在不分析的情况下提升元素。

减少绘制区域

但有时,尽管提升元素,但绘制工作仍然是必要的。绘制问题的一个很大挑战是,浏览器将两个需要绘制的区域联合在一起,这可能导致整个屏幕重绘。例如,如果网页顶部有一个固定的标题,而屏幕底部有正在绘制的内容,则整个屏幕最终都可能会被重新绘制。

减少绘制区域通常是指编排动画和转场效果,以免其出现太多重叠,或设法避免为页面的某些部分添加动画效果。

降低绘制的复杂性

绘制部分屏幕所用的时间。

在谈到绘制时,一些绘制比其他绘制的开销更大。例如,任何涉及模糊(比如阴影)的绘制所需的时间要比绘制红色框所需的时间长。但是,对于 CSS,这一点并不总是很明显:background: red;box-shadow: 0, 4px, 4px, rgba(0,0,0,0.5); 看起来不一定具有截然不同的性能特征,但它们确实具有很大的区别。

通过上面的绘制分析器,您可以确定是否需要寻求其他方式来实现效果。问问自己,是否有可能使用一套价格更低的样式或替代方法来实现最终结果。

您应始终避免在动画播放期间进行绘制,因为每帧的 10 毫秒时间通常不足以完成绘制工作,尤其是在移动设备上。