用CSS开启硬件加速来狠抓网站质量,css3硬件加快

一篇作品说清浏览器解析和CSS(GPU)动画优化

亚洲必赢官网,2017/01/10 · CSS ·
AR

用CSS开启硬件加速来狠抓网站质量,css3硬件加快。原文出处: 黄色的阴影   

深信不疑广大人在做活动端动画的时候遇到了卡顿的题材,那篇小说尝试从浏览器渲染的角度;一点一点告知您动画优化的法则及其技术,作为你工作中优化动画的参阅。文末有优化技术的下结论。

因为GPU合成没有法定正式,每个浏览器的难点和缓解方法也差异;所以文章内容仅供参考。

1. 何为硬件加快

动画片卡顿是在移动web开发时经常境遇的标题,解决那些问题一般会用到css3硬件加快
css3硬件加速本条名字感觉上很巨大上,其实它做的业务能够大约概括为:通过GPU进行渲染,解放cpu。

无线质量优化:Composite

2016/04/26 · 基础技术 ·
无线

原文出处: Taobao前端团队(FED)-
冬萌   

亚洲必赢官网 1

一个 Web 页面的来得,不难的话可以认为经历了以下下多少个步骤。

亚洲必赢官网 2

  • JavaScript:一般的话,我们会动用 JavaScript
    来落到实处部分视觉变化的作用。比如做一个动画片或者往页面里添加一些 DOM
    元素等。
  • Style:总括样式,那个历程是基于 CSS 选取器,对各样 DOM
    元素匹配对应的 CSS 样式。这一步截止之后,就确定了每个 DOM
    元素上该利用什么 CSS 样式规则。
  • Layout:布局,上一步确定了每个 DOM
    元素的体制规则,这一步就是有血有肉测算每个 DOM
    元素最后在显示屏上出示的分寸和职位。web
    页面中元素的布局是争持的,因而一个元素的布局暴发变化,会联动地掀起其他因素的布局爆发变化。比如,“
    元素的升幅的变型会潜移默化其子元素的增进率,其子元素宽度的成形也会再三再四对其外孙子元素暴发潜移默化。由此对此浏览器来说,布局进程是平日发出的。
  • Paint:绘制,本质上就是填充像素的进度。包罗绘制文字、颜色、图像、边框和阴影等,也就是一个
    DOM 元素所有的可视效果。一般的话,这些绘制进度是在多少个层上做到的。
  • Composite:渲染层合并,由上一步可知,对页面中 DOM
    元素的绘图是在多少个层上展开的。在每个层上形成绘制进度之后,浏览器会将所有层按照合理的依次合并成一个图层,然后展现在屏幕上。对于有岗位重叠的元素的页面,那个进度越是首要,因为若是图层的联合顺序出错,将会招致元素展现卓殊。

自然,本文大家只来关怀 Composite 部分。

浏览器渲染

提升动画的优化不得不提及浏览器是怎么渲染一个页面。在从服务器中获得数量后,浏览器会先做分析三类东西:

  • 解析html,xhtml,svg那三类文档,形成dom树。
  • 解析css,产生css rule tree。
  • 解析js,js会通过api来操作dom tree和css rule tree。

分析完成之后,浏览器引擎会通过dom tree和css rule tree来创设rendering
tree:

  • rendering tree和dom
    tree并不完全一样,例如:<head></head>或display:none的事物就不会放在渲染树中。
  • css rule tree首如若成功匹配,并把css rule附加给rendering
    tree的各种element。

在渲染树营造形成后,

  • 浏览器会对那个元素举办固定和布局,这一步也称之为reflow或者layout。
  • 浏览器绘制这一个要素的样式,颜色,背景,大小及边框等,这一步也叫做repaint。
  • 下一场浏览器会将各层的音讯发送给GPU,GPU会将各层合成;展现在显示器上。

纵使将浏览器的渲染进度交给GPU处理,而不是运用自带的比较慢的渲染器。那样就可以使得animation与transition越发百发百中。

现象

通过对照不使用css3加速和使用css3加速三个例证,大家得以看到双方渲染的异样:

亚洲必赢官网 3

不使用css3加速.png

亚洲必赢官网 4

使用css3加速.png

前端通过改动top和left品质举行动画,fps维持在47左右,cpu一向进展计算;后者通过transform完成,fps在62左右,cpu基本不要求统计。比较可以通过transform不仅仅荣升了渲染品质,也解放了cpu。

浏览器渲染原理

在座谈 Composite 在此之前,有必不可少先简单明白下一些浏览器(本文只是对准 Chrome
来说)的渲染原理,方便对之后有的概念的了然。越来越多详细的始末可以参阅 GPU
Accelerated Compositing in
Chrome

注:由于 Chrome 对 Blank
引擎某些达成的改动,某些大家事先熟习的类名有了变更,比如 RenderObject
变成了 LayoutObject,RenderLayer 变成了 PaintLayer。感兴趣的看以参阅
Slimming Paint。

在浏览器中,页面内容是储存为由 Node 对象组成的树状结构,也就是 DOM
树。每一个 HTML element 元素都有一个 Node 对象与之对应,DOM
树的根节点永远都是 Document Node。那点信任我们都很熟练了,但实在,从
DOM 树到最后的渲染,必要展开一些转移映射。

亚洲必赢官网 5

渲染优化原理

如上所说,渲染树打造形成后;浏览器要做的步调:

reflow——》repaint——》composite

我们可以在浏览器中用css开启硬件加快,使GPU (Graphics Processing Unit)
发挥效应,从而升级品质

原理

DOM树和CSS结合后形成渲染树。渲染树中隐含了汪洋的渲染元素,每一个渲染元素会被分到一个图层中,每个图层又会被加载到GPU形成渲染纹理。GPU中transform是不会触发
repaint 的,这点格外相近3D绘图效率,最后那么些使用
transform的图层都会由独立的合成器进度展开拍卖。

透过chrome的timeline工具,肉色框代表要求repaint的片段,红色框代表渲染图层,比较两者可见选用的css3硬件加快后,不会开展repaint操作,而只会发生一个渲染图层,GPU就背负操作那些渲染图层。

亚洲必赢官网 6

不使用css3加速.png

亚洲必赢官网 7

使用css3加速.png

从 Nodes 到 LayoutObjects

DOM 树中得每个 Node 节点都有一个相应的 LayoutObject 。LayoutObject
知道哪些在屏幕上 paint Node 的内容。

reflow和repaint

reflow和repaint都是消耗浏览器品质的操作,那二者尤以reflow为甚;因为老是reflow,浏览器都要再一次统计每个元素的造型和地点。

鉴于reflow和repaint都是优异消耗品质的,我们的浏览器为此做了部分优化。浏览器会将reflow和repaint的操作积攒一批,然后做一遍reflow。然而有些时候,你的代码会强制浏览器做往往reflow。例如:

JavaScript

var content = document.getElementById(‘content’); content.style.width =
700px; var contentWidth = content.offsetWidth; content.style.backgound =
‘red’;

1
2
3
4
var content = document.getElementById(‘content’);
content.style.width = 700px;
var contentWidth = content.offsetWidth;
content.style.backgound = ‘red’;

以上第三行代码,须求浏览器reflow后;再获取值,所以会导致浏览器多做四遍reflow。

上边是有些针对性reflow和repaint的特级实践:

  • 无须一条一条地修改dom的体制,尽量使用className一回修改。
  • 将dom离线后修改
    • 使用documentFragment对象在内存里操作dom。
    • 先把dom节点display:none;(会接触四遍reflow)。然后做大批量的改动后,再把它呈现出来。
    • clone一个dom节点在内存里,修改之后;与在线的节点相替换。
  • 无须选取table布局,一个小改变会招致任何table的再度布局。
  • transform和opacity只会挑起合成,不会挑起布局和重绘。

从上述的一级实践中你或许发现,动画优化一般都是尽量地裁减reflow、repaint的暴发。关于怎么样属性会挑起reflow、repaint及composite,你可以在那些网站找到。

当今超过一半计算机的显卡都辅助硬件加快。鉴于此,我们得以发布GPU的力量,从而使大家的网站或利用表现的愈加流畅。

复合图层

在常理中大家关系transform会创造一个图层,GPU会来执行transform的操作,那几个图层且称为复合图层(composited
layer)。
尽管 Chrome
的启发式方法(heuristic)随着岁月在持续发展前行,不过从脚下来说,满意以下任意意况便会成立层:

  • 3D 或透视变换(perspective transform) CSS 属性
  • 拔取加快摄像解码的元素,如<video>
  • 负有 3D (WebGL) 上下文或加紧的 2D 上下文的要素,如<canvas>
  • 错落插件(如 Flash)
  • 对友好的 opacity 做 CSS 动画或采取一个卡通 webkit 变换的要素
  • 具有加快 CSS 过滤器的要素,如CSS filters
  • 要素有一个暗含复合层的儿孙节点(换句话说,就是一个因素拥有一个子元素,该子元素在协调的层里)
  • 要素有一个 z-index
    较低且带有一个复合层的弟兄元素(换句话说就是该因素在复合层上边渲染)

如果页面建立了过多的复合图层,同样也会促成页面的卡顿。在CSS3硬件加速也有坑那篇文章中,小编介绍了由于z-index造成复合图层过多而引发的难点,在今后开发时可以借鉴。可以调节图层过多卡顿页面叩问z-idnex对图层创立的震慑。

从 LayoutObjects 到 PaintLayers

一般的话,拥有同等的坐标空间的
LayoutObjects,属于同一个渲染层(PaintLayer)。PaintLayer 最初是用来达成
stacking
contest(层叠上下文),以此来保管页面元素以科学的次第合成(composite),那样才能正确的来得元素的交汇以及半晶莹剔透元素等等。由此满意形成层叠上下文条件的
LayoutObject
一定会为其创设新的渲染层,当然还有任何的一些奇特情状,为局地奇特的
LayoutObjects 创设一个新的渲染层,比如 overflow != visible
的因素。根据创立 PaintLayer 的来由莫衷一是,可以将其分为常见的 3 类:

  • NormalPaintLayer
    • 根元素(HTML)
    • 有明显的定点属性(relative、fixed、sticky、absolute)
    • 透明的(opacity 小于 1)
    • 有 CSS 滤镜(fliter)
    • 有 CSS mask 属性
    • 有 CSS mix-blend-mode 属性(不为 normal)
    • 有 CSS transform 属性(不为 none)
    • backface-visibility 属性为 hidden
    • 有 CSS reflection 属性
    • 有 CSS column-count 属性(不为 auto)或者 有 CSS column-width
      属性(不为 auto)
    • 脚下有对于 opacity、transform、fliter、backdrop-filter 应用动画
  • OverflowClipPaintLayer
    • overflow 不为 visible
  • NoPaintLayer
    • 不须求 paint 的
      PaintLayer,比如一个未曾视觉属性(背景、颜色、阴影等)的空 div。

满足上述口径的 LayoutObject 会拥有独立的渲染层,而其他的 LayoutObject
则和其首先个具有渲染层的父元素共用一个。

composite

在reflow和repaint之后,浏览器会将多少个复合层传入GPU;进行合成工作,那么合成是什么工作的吗?

万一大家的页面中有A和B多个元素,它们有absolute和z-index属性;浏览器会重绘它们,然后将图像发送给GPU;然后GPU将会把八个图像合成呈现在显示屏上。

XHTML

<style> #a, #b { position: absolute; } #a { left: 30px; top:
30px; z-index: 2; } #b { z-index: 1; } </style> <div
id=”#a”>A</div> <div id=”#b”>B</div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style>
#a, #b {
position: absolute;
}
 
#a {
left: 30px;
top: 30px;
z-index: 2;
}
 
#b {
z-index: 1;
}
</style>
<div id="#a">A</div>
<div id="#b">B</div>

亚洲必赢官网 8

俺们将A元素使用left属性,做一个平移动画:

XHTML

<style> #a, #b { position: absolute; } #a { left: 10px; top:
10px; z-index: 2; animation: move 1s linear; } #b { left: 50px; top:
50px; z-index: 1; } @keyframes move { from { left: 30px; } to { left:
100px; } } </style> <div id=”#a”>A</div> <div
id=”#b”>B</div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<style>
#a, #b {
position: absolute;
}
 
#a {
left: 10px;
top: 10px;
z-index: 2;
animation: move 1s linear;
}
 
#b {
left: 50px;
top: 50px;
z-index: 1;
}
 
@keyframes move {
from { left: 30px; }
to { left: 100px; }
}
</style>
<div id="#a">A</div>
<div id="#b">B</div>

在这些事例中,对于动画的每一帧;浏览器会总计元素的几何样子,渲染新境况的图像;并把它们发送给GPU。(你没看错,position也会挑起浏览器重排的)即使浏览器做了优化,在repaint时,只会repaint部分区域;可是大家的卡通片依旧不够流畅。

因为重排和重绘爆发在动画的每一帧,一个卓有功用幸免reflow和repaint的方法是我们只有画八个图像;一个是a元素,一个是b元素及任何页面;我们将那两张图纸发送给GPU,然后动画爆发的时候;只做两张图纸相对对方的移动。也就是说,仅仅合成缓存的图片将会快速;那也是GPU的优势——它能万分快地以亚像素精度地合成图片,并给动画带来平滑的曲线。

为了仅爆发composite,大家做动画的css property必须满意以下多少个条件:

  • 不影响文档流。
  • 反对赖文档流。
  • 不会招致重绘。

满足上述以上条件的css
property只有transform和opacity。你可能觉得position也满意上述口径,但实况不是那样,举个例证left属性可以行使比例的值,看重于它的offset
parent。还有em、vh等其余单位也依靠于她们的条件。

俺们使用translate来代替left

XHTML

<style> #a, #b { position: absolute; } #a { left: 10px; top:
10px; z-index: 2; animation: move 1s linear; } #b { left: 50px; top:
50px; z-index: 1; } @keyframes move { from { transform: translateX(0); }
to { transform: translateX(70px); } } </style> <div
id=”#a”>A</div> <div id=”#b”>B</div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<style>
#a, #b {
position: absolute;
}
 
#a {
left: 10px;
top: 10px;
z-index: 2;
animation: move 1s linear;
}
 
#b {
left: 50px;
top: 50px;
z-index: 1;
}
 
@keyframes move {
from { transform: translateX(0); }
to { transform: translateX(70px); }
}
</style>
<div id="#a">A</div>
<div id="#b">B</div>

浏览器在动画执行此前就领悟动画如何开首和得了,因为浏览器没有观察要求reflow和repaint的操作;浏览器就会画两张图像作为复合层,并将它们传播GPU。

诸如此类做有四个优势:

  • 动画片将会那么些流利
  • 动画片不在绑定到CPU,就算js执行大气的劳作;动画依旧流畅。

看起来质量难点好像早就缓解了?在下文你会看到GPU动画的一对题材。

2硬件加快原理

启用

如下几个css属性可以触发硬件加快:

  • transform
  • opacity
  • filter
  • will-change:哪一个特性即将发生变化,进而进行优化。

地点的的例子中用到的是transform
2D,它是在运作时才会成立图层,因而在动画初步和完工时会举行repaint操作;而浏览器在渲染前就为transform
3D创制了图层。

亚洲必赢官网 9

发端时的repaint

亚洲必赢官网 10

利落时的repaint

能够因而transform的3D属性强制开启GPU加快:

  transform: translateZ(0);
  transform: rotateZ(360deg);

从 PaintLayers 到 GraphicsLayers

好几特殊的渲染层会被认为是合成层(Compositing Layers),合成层拥有独立的
GraphicsLayer,而其他不是合成层的渲染层,则和其首先个有着 GraphicsLayer
父层公用一个。

每个 GraphicsLayer 都有一个 GraphicsContext,GraphicsContext
会负责输出该层的位图,位图是储存在共享内存中,作为纹理上传到 GPU
中,最终由 GPU 将多个位图举行合成,然后 draw
到显示屏上,此时,大家的页面也就展现到了显示器上。

渲染层升高为合成层的因由有须臾间两种:

注:渲染层进步为合成层有一个先决条件,该渲染层必须是
SelfPaintingLayer(基本可认为是上文介绍的
诺玛lPaintLayer)。以下所探究的渲染层提高为合成层的情况都是在该渲染层为
SelfPaintingLayer 前提下的。

  • 直接原因(direct reason)
    • 硬件加快的 iframe 元素(比如 iframe
      嵌入的页面中有合成层)demo
    • video 元素
    • 覆盖在 video 元素上的视频控制栏
    • 3D 或者 硬件加快的 2D Canvas 元素
      • demo:普通 2D Canvas
        不会升级为合成层
      • demo:3D Canvas
        提高为合成层
    • 硬件加速的插件,比如 flash 等等
    • 在 DPI 较高的显示器上,fix
      定位的要素会活动地被提高到合成层中。但在 DPI
      较低的装置上却并非如此,因为这么些渲染层的升级会使得字体渲染形式由子像素变为灰阶(详细内容请参见:Text
      Rendering)
    • 有 3D transform
    • backface-visibility 为 hidden
    • 对 opacity、transform、fliter、backdropfilter 应用了 animation
      或者 transition(需假如 active 的 animation 或者 transition,当
      animation 或者 transition
      效果未起初或终止后,提高合成层也会失灵)

      • demo:animation
      • demo:transition亚洲必赢官网 11
    • will-change 设置为
      opacity、transform、top、left、bottom、right(其中 top、left
      等急需设置醒目标稳定属性,如 relative
      等)demo
  • 后人元素原因
    • 有合成层后代同时自己有 transform、opactiy(小于
      1)、mask、fliter、reflection 属性
      demo
    • 有合成层后代同时自身 overflow 不为
      visible(假若自身是因为肯定的平昔因素暴发的
      SelfPaintingLayer,则要求 z-index 不为 auto)
      demo
    • 有合成层后代同时自身 fixed 定位
      demo
    • 有 3D transfrom 的合成层后代同时自身有 preserves-3d 属性
      demo
    • 有 3D transfrom 的合成层后代同时自身有 perspective 属性
      demo
  • overlap
    重叠原因为啥会因为重叠原因此发生合成层呢?举个大概的栗子。亚洲必赢官网 12藏蓝色的矩形重叠在黄色矩形之上,同时它们的父元素是一个
    GraphicsLayer。此时如果肉色矩形为一个 GraphicsLayer,若是 overlap
    不可能提拔合成层的话,那么黑色矩形不会进步为合成层,也就会和父元素公用一个
    GraphicsLayer。亚洲必赢官网 13此刻,渲染顺序就会发出错误,因而为确保渲染顺序,overlap
    也改为了合成层暴发的来由,也就是之类的健康情况。亚洲必赢官网 14理所当然
    overlap 的原因也会细分为几类,接下去大家会详细看下。

    • 臃肿或者说部分重叠在一个合成层之上。那什么终究重叠呢,最普遍和不难了解的就是因素的
      border box(content + padding + border)
      和合成层的有重叠,比如:demo,当然
      margin area
      的重合是无用的(demo)。其他的还有一对不普遍的意况,也毕竟同合成层重叠的规格,如下:

      • filter 效果同合成层重叠
        demo
      • transform 变换后同合成层重叠
        demo
      • overflow scroll 意况下同合成层重叠。即只要一个 overflow
        scroll(不管 overflow:auto 还是
        overflow:scrill,只若是能 scroll 即可)
        的要素同一个合成层重叠,则其可视子元素也同该合成层重叠
        demo
    • 假定重叠在一个合成层之上(assumedOverlap)。那么些原因听上去有点虚,什么叫借使重叠?其实也相比好领悟,比如一个元素的
      CSS
      动画功用,动画运行时期,元素是有可能和其余因素有臃肿的。针对于那种情景,于是就有了
      assumedOverlap
      的合成层爆发原因,示例可知:demo。在本
      demo 中,动画元素视觉上并不曾和其兄弟元素重叠,但因为
      assumedOverlap
      的缘由,其兄弟元素依旧升高为了合成层。需要小心的是该原因下,有一个很新鲜的意况:若是合成层有内联的
      transform 属性,会招致其兄弟渲染层 assume
      overlap,从而升级为合成层。比如:demo。

GPU是何许合成图像的

GPU实际上可以当作一个独门的总括机,它有温馨的统计机和存储器及数码处理模型。当浏览器向GPU发送信息的时候,如同向一个外部设备发送音信。

你可以把浏览器向GPU发送数据的长河,与使用ajax向服务器发送音信卓殊类似。想转手,你用ajax向服务器发送数据,服务器是不会一贯收受浏览器的仓储的消息的。你需求收集页面上的数据,把它们放进一个载体里面(例如JSON),然后发送数据到长途服务器。

平等的,浏览器向GPU发送数据也亟需先创立一个载体;只然则GPU距离CPU很近,不会像远程服务器那样可能几千里那么远。可是对于远程服务器,2秒的延迟是足以承受的;可是对于GPU,几飞秒的推移都会造成动画的卡顿。

浏览器向GPU发送的多少载体是哪些?那里给出一个粗略的创建载体,并把它们发送到GPU的进度。

  • 画每个复合层的图像
  • 预备图层的数额
  • 准备动画的着色器(尽管必要)
  • 向GPU发送数据

之所以你可以看出,每一趟当您添加transform:translateZ(0)will-change:transform给一个元素,你都会做相同的办事。重绘是卓殊消耗品质的,在此地它越是缓慢。在大部景观,浏览器不能够增量重绘。它只好重绘先前被复合层覆盖的区域。

浏览器接收到页面文档后,会将文档中的标记语言分析为DOM树。DOM树和CSS结合后形成浏览器打造页面的渲染树。渲染树中带有了大批量的渲染元素,每一个渲染元素会被分到一个图层中,每个图层又会被加载到GPU形成渲染纹理,而图层在GPU中transform 是不会触发
repaint
的,最后那几个使用 transform 的图层都会由独立的合成器进度展开拍卖。

注意事项
  • 不可能让每个元素都启用硬件加快,那样会暂用很大的内存,使页面会有很强的卡顿感。
  • GPU渲染会潜移默化字体的抗锯齿效果。那是因为GPU和CPU具有差其他渲染机制,即便最后硬件加快甘休了,文本依旧会在动画期间显得得很模糊。

层压缩

大致周边的一些合成层的进步原因如上所说,你会意识,由于重叠的原委,可能随便就会暴发出多量合成层来,而各种合成层都要消耗
CPU
和内存资源,岂不是严重影响页面质量。那或多或少浏览器也考虑到了,因而就有了层压缩(Layer
Squashing)的处理。若是多少个渲染层同一个合成层重叠时,那么些渲染层会被缩减到一个
GraphicsLayer
中,以免备出于重叠原因造成可能现身的“层爆炸”。具体能够看如下
demo。一早先,粉红色方块由于
translateZ
升高为了合成层,其余的方框元素因为重叠的原因,被减去了共同,大小就是带有这3 个方块的矩形大小。

亚洲必赢官网 15

当大家 hover 黑色方块时,会给其设置 translateZ
属性,导致蓝色方块也被升级为合成层,则剩下的多个被收缩到了同步,大小就缩短为涵盖那2 个方块的矩形大小。

亚洲必赢官网 16

理所当然,浏览器的活动的层压缩也不是出将入相的,有这多少个一定情景下,浏览器是无能为力开展层压缩的,如下所示,而这么些情况也是大家应有尽量防止的。(注:以下景况都是根据重叠原由此言)

  • 不可以进展会打破渲染顺序的缩减(squashingWouldBreakPaintOrder)示例如下:demo
CSS

\#ancestor { -webkit-mask-image:
-webkit-linear-gradient(rgba(0,0,0,1), rgba(0,0,0,0)); }
\#composited { width: 100%; height: 100%; transform: translateZ(0);
} \#container { position: relative; width: 400px; height: 60px;
border: 1px solid black; } \#overlap-child { position: absolute;
left: 0; top: 0 ; bottom: 0px; width: 100%; height: 60px;
background-color: orange; }

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-10">
10
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-11">
11
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-12">
12
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-13">
13
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-14">
14
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-15">
15
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-16">
16
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-17">
17
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-18">
18
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-19">
19
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-20">
20
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-21">
21
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-22">
22
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-23">
23
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-24">
24
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-25">
25
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-26">
26
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6d201886f149137440-1" class="crayon-line">
  #ancestor {
</div>
<div id="crayon-5b8f6d201886f149137440-2" class="crayon-line crayon-striped-line">
    -webkit-mask-image: -webkit-linear-gradient(rgba(0,0,0,1), rgba(0,0,0,0));
</div>
<div id="crayon-5b8f6d201886f149137440-3" class="crayon-line">
  }
</div>
<div id="crayon-5b8f6d201886f149137440-4" class="crayon-line crayon-striped-line">
  
</div>
<div id="crayon-5b8f6d201886f149137440-5" class="crayon-line">
  #composited {
</div>
<div id="crayon-5b8f6d201886f149137440-6" class="crayon-line crayon-striped-line">
    width: 100%;
</div>
<div id="crayon-5b8f6d201886f149137440-7" class="crayon-line">
    height: 100%;
</div>
<div id="crayon-5b8f6d201886f149137440-8" class="crayon-line crayon-striped-line">
    transform: translateZ(0);
</div>
<div id="crayon-5b8f6d201886f149137440-9" class="crayon-line">
  }
</div>
<div id="crayon-5b8f6d201886f149137440-10" class="crayon-line crayon-striped-line">
 
</div>
<div id="crayon-5b8f6d201886f149137440-11" class="crayon-line">
  #container {
</div>
<div id="crayon-5b8f6d201886f149137440-12" class="crayon-line crayon-striped-line">
    position: relative;
</div>
<div id="crayon-5b8f6d201886f149137440-13" class="crayon-line">
    width: 400px;
</div>
<div id="crayon-5b8f6d201886f149137440-14" class="crayon-line crayon-striped-line">
    height: 60px;
</div>
<div id="crayon-5b8f6d201886f149137440-15" class="crayon-line">
    border: 1px solid black;
</div>
<div id="crayon-5b8f6d201886f149137440-16" class="crayon-line crayon-striped-line">
  }
</div>
<div id="crayon-5b8f6d201886f149137440-17" class="crayon-line">
 
</div>
<div id="crayon-5b8f6d201886f149137440-18" class="crayon-line crayon-striped-line">
  #overlap-child {
</div>
<div id="crayon-5b8f6d201886f149137440-19" class="crayon-line">
    position: absolute;
</div>
<div id="crayon-5b8f6d201886f149137440-20" class="crayon-line crayon-striped-line">
    left: 0;
</div>
<div id="crayon-5b8f6d201886f149137440-21" class="crayon-line">
    top: 0 ;
</div>
<div id="crayon-5b8f6d201886f149137440-22" class="crayon-line crayon-striped-line">
    bottom: 0px;
</div>
<div id="crayon-5b8f6d201886f149137440-23" class="crayon-line">
    width: 100%;
</div>
<div id="crayon-5b8f6d201886f149137440-24" class="crayon-line crayon-striped-line">
    height: 60px;
</div>
<div id="crayon-5b8f6d201886f149137440-25" class="crayon-line">
    background-color: orange;
</div>
<div id="crayon-5b8f6d201886f149137440-26" class="crayon-line crayon-striped-line">
  }
</div>
</div></td>
</tr>
</tbody>
</table>




XHTML

&lt;div id="container"&gt; &lt;div id="composited"&gt;Text behind
the orange box.&lt;/div&gt; &lt;div id="ancestor"&gt; &lt;div
id="overlap-child"&gt;&lt;/div&gt; &lt;/div&gt; &lt;/div&gt;

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6d201887b075031864-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201887b075031864-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201887b075031864-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201887b075031864-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201887b075031864-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201887b075031864-6">
6
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6d201887b075031864-1" class="crayon-line">
&lt;div id=&quot;container&quot;&gt;
</div>
<div id="crayon-5b8f6d201887b075031864-2" class="crayon-line crayon-striped-line">
  &lt;div id=&quot;composited&quot;&gt;Text behind the orange box.&lt;/div&gt;
</div>
<div id="crayon-5b8f6d201887b075031864-3" class="crayon-line">
  &lt;div id=&quot;ancestor&quot;&gt;
</div>
<div id="crayon-5b8f6d201887b075031864-4" class="crayon-line crayon-striped-line">
    &lt;div id=&quot;overlap-child&quot;&gt;&lt;/div&gt;
</div>
<div id="crayon-5b8f6d201887b075031864-5" class="crayon-line">
  &lt;/div&gt;
</div>
<div id="crayon-5b8f6d201887b075031864-6" class="crayon-line crayon-striped-line">
&lt;/div&gt;
</div>
</div></td>
</tr>
</tbody>
</table>

  • video 元素的渲染层不能被核减同时也无力回天将其他渲染层压缩到 video
    所在的合成层上(squashingVideoIsDisallowed)demo
  • iframe、plugin
    的渲染层不可以被核减同时也无力回天将其余渲染层压缩到其所在的合成层上(squashingLayoutPartIsDisallowed)demo
  • 不可以回落有 reflection
    属性的渲染层(squashingReflectionDisallowed)demo
  • 不知所厝回落有 blend mode
    属性的渲染层(squashingBlendingDisallowed)demo
  • 当渲染层同合成层有不相同的剪裁容器(clipping
    container)时,该渲染层不能够回落(squashingClippingContainerMismatch)。示例如下:demo
CSS

.clipping-container { overflow: hidden; height: 10px;
background-color: blue; } .composited { transform: translateZ(0);
height: 10px; background-color: red; } .target { position:absolute;
top: 0px; height:100px; width:100px; background-color: green; color:
\#fff; }

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-10">
10
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-11">
11
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-12">
12
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-13">
13
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-14">
14
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-15">
15
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-16">
16
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-17">
17
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-18">
18
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-19">
19
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-20">
20
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-21">
21
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-22">
22
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-23">
23
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6d2018880297868155-1" class="crayon-line">
.clipping-container {
</div>
<div id="crayon-5b8f6d2018880297868155-2" class="crayon-line crayon-striped-line">
 
</div>
<div id="crayon-5b8f6d2018880297868155-3" class="crayon-line">
    overflow: hidden;
</div>
<div id="crayon-5b8f6d2018880297868155-4" class="crayon-line crayon-striped-line">
    height: 10px; 
</div>
<div id="crayon-5b8f6d2018880297868155-5" class="crayon-line">
    background-color: blue;
</div>
<div id="crayon-5b8f6d2018880297868155-6" class="crayon-line crayon-striped-line">
  }
</div>
<div id="crayon-5b8f6d2018880297868155-7" class="crayon-line">
 
</div>
<div id="crayon-5b8f6d2018880297868155-8" class="crayon-line crayon-striped-line">
  .composited {
</div>
<div id="crayon-5b8f6d2018880297868155-9" class="crayon-line">
 
</div>
<div id="crayon-5b8f6d2018880297868155-10" class="crayon-line crayon-striped-line">
    transform: translateZ(0); 
</div>
<div id="crayon-5b8f6d2018880297868155-11" class="crayon-line">
    height: 10px; 
</div>
<div id="crayon-5b8f6d2018880297868155-12" class="crayon-line crayon-striped-line">
    background-color: red;
</div>
<div id="crayon-5b8f6d2018880297868155-13" class="crayon-line">
  }
</div>
<div id="crayon-5b8f6d2018880297868155-14" class="crayon-line crayon-striped-line">
 
</div>
<div id="crayon-5b8f6d2018880297868155-15" class="crayon-line">
  .target {
</div>
<div id="crayon-5b8f6d2018880297868155-16" class="crayon-line crayon-striped-line">
 
</div>
<div id="crayon-5b8f6d2018880297868155-17" class="crayon-line">
    position:absolute; 
</div>
<div id="crayon-5b8f6d2018880297868155-18" class="crayon-line crayon-striped-line">
    top: 0px; 
</div>
<div id="crayon-5b8f6d2018880297868155-19" class="crayon-line">
    height:100px; 
</div>
<div id="crayon-5b8f6d2018880297868155-20" class="crayon-line crayon-striped-line">
    width:100px; 
</div>
<div id="crayon-5b8f6d2018880297868155-21" class="crayon-line">
    background-color: green;
</div>
<div id="crayon-5b8f6d2018880297868155-22" class="crayon-line crayon-striped-line">
    color: #fff;
</div>
<div id="crayon-5b8f6d2018880297868155-23" class="crayon-line">
  }
</div>
</div></td>
</tr>
</tbody>
</table>




XHTML

&lt;div class="clipping-container"&gt; &lt;div
class="composited"&gt;&lt;/div&gt; &lt;/div&gt; &lt;div
class="target"&gt;不会被压缩到 composited div 上&lt;/div&gt;

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6d2018884301689224-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018884301689224-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018884301689224-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018884301689224-4">
4
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6d2018884301689224-1" class="crayon-line">
&lt;div class=&quot;clipping-container&quot;&gt;
</div>
<div id="crayon-5b8f6d2018884301689224-2" class="crayon-line crayon-striped-line">
  &lt;div class=&quot;composited&quot;&gt;&lt;/div&gt;
</div>
<div id="crayon-5b8f6d2018884301689224-3" class="crayon-line">
&lt;/div&gt;
</div>
<div id="crayon-5b8f6d2018884301689224-4" class="crayon-line crayon-striped-line">
&lt;div class=&quot;target&quot;&gt;不会被压缩到 composited div 上&lt;/div&gt;
</div>
</div></td>
</tr>
</tbody>
</table>


本例中 .target 同 合成层 `.composited` 重叠,但是由于
.composited`在一个 overflow: hidden 的容器中,导致 .target 和合成层有不同的裁剪容器,从而 `.target` 无法被压缩。`

  • 绝对于合成层滚动的渲染层不可以被削减(scrollsWithRespectToSquashingLayer)示例如下:demo

CSS

body { height: 1500px; overflow-x: hidden; } .composited { width: 50px;
height: 50px; background-color: red; position: absolute; left: 50px;
top: 400px; transform: translateZ(0); } .overlap { width: 200px; height:
200px; background-color: green; position: fixed; left: 0px; top: 0px; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
body {
    height: 1500px;
    overflow-x: hidden;
  }
 
  .composited {
 
    width: 50px;
    height: 50px;
    background-color: red;
    position: absolute;
    left: 50px;
    top: 400px;
    transform: translateZ(0);
  }
 
  .overlap {
    width: 200px;
    height: 200px;
    background-color: green;
    position: fixed;
    left: 0px;
    top: 0px;
  }

XHTML

<div class=”composited”></div> <div
class=”overlap”></div>

1
2
<div class="composited"></div>
<div class="overlap"></div>

本例中,红色的
.composited提升为了合成层,绿色的.overlapfix 在页面顶部,一开始只有.composited合成层。

![]()

当滑动页面,.overlap重叠到.composited上时,.overlap`
会因重叠原因提高为合成层,同时,因为相对于合成层滚动,因而不能被裁减。

![]()

  • 当渲染层同合成层有例外的所有 opacity 的祖先层(一个安装了 opacity
    且小于 1,一个并未安装
    opacity,也算是差异)时,该渲染层不可以回落(squashingOpacityAncestorMismatch,同
    squashingClippingContainerMismatch)demo
  • 当渲染层同合成层有两样的装有 transform
    的上代层时,该渲染层无法回落(squashingTransformAncestorMismatch,同上)
    demo
  • 当渲染层同合成层有分歧的具有 filter
    的祖辈层时,该渲染层不可以回落(squashingFilterAncestorMismatch,同上)demo
  • 当覆盖的合成层正在运行动画时,该渲染层不可能回落(squashingLayerIsAnimating),当动画未先导依然运行达成之后,该渲染层才方可被压缩
    demo亚洲必赢官网 17

隐式合成

还记得刚才a元素和b元素动画的例子吗?现在大家将b元素做动画,a元素静止不动。

亚洲必赢官网 18

和刚刚的事例不一致,现在b元素将持有一个单身复合层;然后它们将被GPU合成。可是因为a元素要在b元素的方面(因为a元素的z-index比b元素高),那么浏览器会做什么?浏览器会将a元素也单独做一个复合层!

故此我们现在有多少个复合层a元素所在的复合层、b元素所在的复合层、其余内容及背景层。

一个或四个没有和谐复合层的因素要出新在有复合层元素的顶端,它就会具有和谐的复合层;那种处境被叫做隐式合成。

浏览器将a元素升高为一个复合层有很种种缘故,上边罗列了一些:

  • 3d或透视变换css属性,例如translate3d,translateZ等等(js一般经过那种艺术,使元素得到复合层)
  • <video><iframe><canvas><webgl>等元素。
  • 掺杂插件(如flash)。
  • 要素自身的 opacity和transform 做 CSS 动画。
  • 装有css过滤器的要素。
  • 使用will-change属性。
  • position:fixed。
  • 要素有一个 z-index
    较低且含有一个复合层的哥们儿元素(换句话说就是该因素在复合层下面渲染)

那看起来css动画的属性瓶颈是在重绘上,不过真实的题材是在内存上:

CSS transform 会创立了一个新的复合图层,可以被GPU间接用来施行 transform 操作。

参考文章:
  1. CSS动画之硬件加快:小编相比详细介绍了硬件加快,计算的很到位。
  2. CSS3硬件加快也有坑:
    小编介绍了是因为z-index造成复合图层过多,以后开发加以注意。
  3. 运用CSS3
    will-change提升页面滚动、动画等渲染品质:
    will-change的介绍
  4. javascript品质优化-repaint和reflow:性能杀手以及优化措施。
  5. 两张图解释CSS动画的属性:比较详细相比较了使用硬件加速和不使用硬件加速的流水线差距。

怎么着查看合成层

应用 Chrome DevTools 工具来查阅页面中合成层的景色。

比较简单的点子是开拓 DevTools,勾选上 Show layer borders

亚洲必赢官网 19

里头,页面上的合成层会用蓝色边框框出来。

亚洲必赢官网 20

自然,尤其详细的音信可以透过 提姆eline 来查看。

每一个单独的帧,看到各种帧的渲染细节:

亚洲必赢官网 21

点击之后,你就会在视图中观望一个新的选项卡:Layers。

亚洲必赢官网 22

点击那几个 Layers
选项卡,你会看到一个新的视图。在那些视图中,你可以对这一帧中的所有合成层进行扫描、缩放等操作,同时仍可以见到各种渲染层被创建的原故。

亚洲必赢官网 23

有了这一个视图,你就能精通页面中到底有多少个合成层。如果你在对页面滚动或渐变效果的习性分析中窥见
Composite
进程花费了太多时间,那么你可以从这些视图里看看页面中有稍许个渲染层,它们为啥被创建,从而对合成层的多寡进行优化。

内存占用

利用GPU动画需要发送多张渲染层的图像给GPU,GPU也亟需缓存它们以便于继续动画的运用。

一个渲染层,必要有些内存占用?为了方便了然,举一个几乎的例子;一个宽、高都是300px的纯色图像须求多少内存?

300 300 4 =
360000字节,即360kb。那里乘以4是因为,每个像素需求多个字节计算机内存来描述。

如果大家做一个轮播图组件,轮播图有10张图纸;为了完毕图片间平滑对接的互相;为每个图像添加了will-change:transform。那将升格图像为复合层,它将多必要19mb的长空。800
600 4 * 10 = 1920000。

唯有是一个轮播图组件就要求19m的附加空间!

在chrome的开发者工具中打开setting——》Experiments——》layers可以见见各类层的内存占用。如图所示:

亚洲必赢官网 24

亚洲必赢官网 25

浏览器什么日期会成立一个独自的复合图层呢?事实上一般是在以下三种处境下:

属性优化

升级为合成层简单说来有以下几点好处:

  • 合成层的位图,会交由 GPU 合成,比 CPU 处理要快
  • 当要求 repaint 时,只须求 repaint 本身,不会潜移默化到其它的层
  • 对于 transform 和 opacity 效果,不会触发 layout 和 paint

接纳合成层对于升级页面质量方面有很大的作用,因而大家也总计了须臾间几点优化提议。

GPU动画的亮点和瑕疵

当今大家可以总括一下GPU动画的长处和缺陷:

  • 每秒60帧,动画平滑、流畅。
  • 一个适龄的动画片工作在一个独立的线程,它不会被大批量的js计算阻塞。
  • 3D“变换”是有利的。

缺点:

  • 晋级一个因素到复合层须求极度的重绘,有时那是慢的。(即大家收获的是一个全层重绘,而不是一个增量)
  • 绘图层必须传输到GPU。取决于层的数据和传导可能会卓越缓慢。那说不定让一个因素在低档设备上闪烁。
  • 每个复合层都必要消耗额外的内存,过多的内存可能造成浏览器的倒台。
  • 要是你不考虑隐式合成,而利用重绘;会招致额外的内存占用,并且浏览器崩溃的票房价值是极度高的。
  • 俺们会有视觉假象,例如在Safari中的文本渲染,在某些情状下页面内容将一去不返或变形。
  • 3D 或者 CSS transform
  • <video> 和 <canvas> 标签
  • CSS filters
  • 要素覆盖时,比如选用了 z-index 属性

升高动画效果的要素

合成层的补益是不会潜移默化到其余因素的绘图,因此,为了减小动画元素对任何因素的影响,从而收缩paint,大家需要把动画效果中的元素升高为合成层。

进步合成层的最好点子是使用 CSS 的 will-change
属性。从上一节合成层爆发原因中,可以了解 will-change 设置为
opacity、transform、top、left、bottom、right 可以将元素进步为合成层。

CSS

#target { will-change: transform; }

1
2
3
#target {
  will-change: transform;
}

其匹配如下所示:
亚洲必赢官网 26

对于这一个如今还不接济 will-change 属性的浏览器,近期常用的是利用一个 3D
transform 属性来强制提升为合成层:

CSS

#target { transform: translateZ(0); }

1
2
3
#target {
  transform: translateZ(0);
}

但必要注意的是,不要成立太多的渲染层。因为每创立一个新的渲染层,就代表新的内存分配和更扑朔迷离的层的管住。之后大家会详细座谈。

即使你已经把一个因素放到一个新的合成层里,那么可以动用 Timeline
来确认这么做是还是不是真的创新了渲染质量。别盲目进步合成层,一定要分析其实际品质表现。

优化技术

 

行使 transform 或者 opacity 来贯彻动画效果

小说最开首,大家讲到了页面显示出来所经历的渲染流水线,其实从性能方面考虑,最优秀的渲染流水线是从未有过布局和制图环节的,只须求做合成层的集合即可:

亚洲必赢官网 27

为了促成上述功能,就须要只使用那多少个仅触发 Composite
的习性。近期,唯有多个特性是知足这几个原则的:transforms 和
opacity。更详细的新闻可以查阅 CSS Triggers。

留意:元素升高为合成层后,transform 和 opacity 才不会触发
paint,如果不是合成层,则其如故会触发 paint。具体见如下三个 demo。

  • demo
    1:transform亚洲必赢官网 28
  • demo
    2:opacity亚洲必赢官网 29

可以见到未升级 target element 为合成层,transform 和 opacity 仍然会触发
paint。

幸免隐式合成

  • 维持动画的目的的z-index尽可能的高。理想的,那么些元素应该是body元素的直白子元素。当然,那不是总可能的。所以你可以仿造一个元素,把它身处body元素下独自是为着做动画。
  • 将元素上安装will-change
    CSS属性,元素上有了这个特性,浏览器会进步这几个因素变为一个复合层(不是连接)。那样动画就足以平滑的发端和了结。可是毫无滥用这些特性,否则会大大伸张内存消耗。

3 为啥硬件加速会使页面流畅

减掉绘制区域

对此不要求再一次绘制的区域应尽量幸免绘制,以缩减绘制区域,比如一个 fix
在页面顶部的平素不变的导航 header,在页面内容某个区域 repaint
时,整个屏幕包涵 fix 的 header 也会被重绘,见
demo,结果如下:

亚洲必赢官网 30

而对于固定不变的区域,大家目的在于其并不会被重绘,由此得以通过事先的办法,将其进步为独立的合成层。

压缩绘制区域,必要仔细分析页面,区分绘制区域,减弱重绘区域仍旧幸免重绘。

卡通中只行使transform和opacity

如上所说,transform和opacity保障了元素属性的浮动不影响文档流、也不受文档流影响;并且不会促成repaint。有些时候你可能想要改变其余的css属性,作为动画。例如:你也许想使用background属性改变背景:

CSS

<div class=”bg-change”></div> .bg-change { width: 100px;
height: 100px; background: red; transition: opacity 2s; }
.bg-change:hover { background: blue; }

1
2
3
4
5
6
7
8
9
10
<div class="bg-change"></div>
.bg-change {
  width: 100px;
  height: 100px;
  background: red;
  transition: opacity 2s;
}
.bg-change:hover {
  background: blue;
}

在那几个事例中,在动画的每一步;浏览器都会进展一回重绘。大家可以动用一个复层在这一个元素上边,并且独自变换opacity属性:

XHTML

<div class=”bg-change”></div> <style> .bg-change {
width: 100px; height: 100px; background: red; } .bg-change::before {
content: ”; display: block; width: 100%; height: 100%; background:
blue; opacity: 0; transition: opacity 20s; } .bg-change:hover::before {
opacity: 1; } </style>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div class="bg-change"></div>
<style>
.bg-change {
  width: 100px;
  height: 100px;
  background: red;
}
.bg-change::before {
  content: ”;
  display: block;
  width: 100%;
  height: 100%;
  background: blue;
  opacity: 0;
  transition: opacity 20s;
}
.bg-change:hover::before {
  opacity: 1;
}
</style>

因为 transform 属性不会触发浏览器的
repaint(重绘),而相对定位absolute中的 left 和 top 则会一直触发
repaint(重绘)。

理所当然管理合成层

看完上边的稿子,你会意识升高合成层会落得更好的属性。那看起来万分诱人,不过难点是,创造一个新的合成层并不是免费的,它得消耗额外的内存和管制资源。实际上,在内存资源有限的配备上,合成层带来的属性改良,可能远远赶不上过多合成层开支给页面品质带来的负面影响。同时,由于各样渲染层的纹路都急需上盛传
GPU 处理,由此大家还须求考虑 CPU 和 GPU 之间的带宽难题、以及有多大内存供
GPU 处理这一个纹理的难点。

对于合成层占用内存的题材,我们大约做了多少个 demo 举行了认证。

demo
1
和 demo
2
中,会创立 2000 个一样的 div 元素,分歧的是 demo
2
中的元素通过 will-change 都提高为了合成层,而八个 demo
页面的内存消耗却有很分明的差别。

亚洲必赢官网 31

减小复合层的尺码

看一下两张图片,有啥分歧啊?

亚洲必赢官网 32

那两张图片视觉上是相同的,可是它们的尺寸一个是39kb;其余一个是400b。分化之处在于,第四个纯色层是因此scale放大10倍做到的。

XHTML

<div id=”a”></div> <div id=”b”></div>
<style> #a, #b { will-change: transform; } #a { width: 100px;
height: 100px; } #b { width: 10px; height: 10px; transform: scale(10);
} </style>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="a"></div>
<div id="b"></div>
 
<style>
#a, #b {
will-change: transform;
}
 
#a {
width: 100px;
height: 100px;
}
 
#b {
width: 10px;
height: 10px;
transform: scale(10);
}
</style>

对此图片,你要如何是好吗?你可以将图纸的尺寸裁减5%——10%,然后利用scale将它们放大;用户不会看到什么样界别,然则你可以减掉大气的储存空间。

怎么 transform 没有触发 repaint 呢?简单的说,transform
动画由GPU控制,帮助硬件加快,并不须要软件上面的渲染。

预防层爆炸

经过从前的牵线,大家了解同合成层重叠也会使元素提高为合成层,纵然有浏览器的层压缩编制,可是也有好多不可能举办削减的情事。也就是说除了大家显式的宣示的合成层,还可能是因为重叠原因不经意间发生局地不在预期的合成层,极端一点可能会时有暴发大量的额外合成层,出现层爆炸的现象。大家简要写了一个格外点但实际在大家的页面中相比较广泛的
demo。

CSS

@-webkit-keyframes slide { from { transform: none; } to { transform:
translateX(100px); } } .animating { width: 300px; height: 30px;
background-color: orange; color: #fff; -webkit-animation: slide 5s
alternate linear infinite; } ul { padding: 5px; border: 1px solid #000;
} .box { width: 600px; height: 30px; margin-bottom: 5px;
background-color: blue; color: #fff; position: relative; /*
会导致力不从心回落:squashingClippingContainerMismatch */ overflow: hidden;
} .inner { position: absolute; top: 2px; left: 2px; font-size: 16px;
line-height: 16px; padding: 2px; margin: 0; background-color: green; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@-webkit-keyframes slide {
    from { transform: none; }
    to { transform: translateX(100px); }
    }
    .animating {
    
    width: 300px;
    height: 30px;
    background-color: orange;
    color: #fff;
      -webkit-animation: slide 5s alternate linear infinite;
    }
 
  ul {
 
    padding: 5px;
    border: 1px solid #000;
  }
 
    .box {
 
    width: 600px;
    height: 30px;
    margin-bottom: 5px;
    background-color: blue;
    color: #fff;
    position: relative;
    /* 会导致无法压缩:squashingClippingContainerMismatch */
    overflow: hidden;
    }
 
    .inner {
      position: absolute;
      top: 2px;
      left: 2px;
      font-size: 16px;
      line-height: 16px;
      padding: 2px;
      margin: 0;
      background-color: green;
    }

XHTML

<!– 动画合成层 –> <div class=”animating”>composited
animating</div> <ul> <!– assume overlap –> <li
class=”box”> <!– assume overlap –> <p
class=”inner”>asume overlap, 因为 squashingClippingContainerMismatch
无法回落</p> </li> … </ul>

1
2
3
4
5
6
7
8
9
10
11
<!– 动画合成层 –>
<div class="animating">composited animating</div>
<ul>
  <!– assume overlap –>
  <li class="box">
    <!– assume overlap –>
    <p class="inner">asume overlap, 因为 squashingClippingContainerMismatch 无法压缩</p>
  </li>
  
  …
</ul>

demo
中,.animating 的合成层在运行动画,会导致 .inner
元素因为上文介绍过的 assumedOverlap
的由来,而被升级为合成层,同时,.inner 的父元素 .box 设置了
overflow: hidden,导致 .inner 的合成层因为
squashingClippingContainerMismatch
的原故,无法回落,就出现了层爆炸的标题。

亚洲必赢官网 33

那种景况平日在我们的事情中依旧很广阔的,比如 slider + list
的协会,一旦满意了不可以展开层压缩的图景,就很简单出现层爆炸的题材。

解决层爆炸的题材,最佳方案是打破 overlap
的尺度,也就是说让此外因素不要和合成层元素重叠。对于上述的演示,大家得以将
.animation 的 z-index 提高。修改后
demo

CSS

.animating { … /* 让此外因素不和合成层重叠 */ position: relative;
z-index: 1; }

1
2
3
4
5
6
7
.animating {
  
  …
  /* 让其他元素不和合成层重叠 */
  position: relative;
  z-index: 1;
}

此时,就只有 .animating 提高为合成层,如下:

亚洲必赢官网 34

同时,内存占用相比较以前也下滑了众多。

亚洲必赢官网 35

一经受限于视觉要求等因素,其余因素必须求遮盖在合成层之上,那应该尽量幸免不可能层压缩景况的面世。针对上述示范中,无法层压缩的情景(squashingClippingContainerMismatch),大家得以将
.boxoverflow: hidden
去掉,那样就足以选拔浏览器的层压缩了。修改后
demo

那时候,由于第四个 .box 因为 squashingLayerIsAnimating
的来头不能回落,其他的都被核减到了一块儿。

亚洲必赢官网 36

还要,内存占用比较此前也暴跌了成百上千。

亚洲必赢官网 37

用css动画而不是js动画

css动画有一个第一的特色,它是一心工作在GPU上。因为你申明了一个卡通怎么着起始和怎么收场,浏览器会在动画初叶前准备好所有需求的下令;并把它们发送给GPU。而一旦运用js动画,浏览器必须统计每一帧的场地;为了保障平滑的动画片,咱们务必在浏览器主线程统计新情景;把它们发送给GPU至少60次每秒。除了总结和发送数据比css动画要慢,主线程的载重也会影响动画;
当主线程的总结职务过多时,会招致动画的延期、卡顿。

据此尽量地利用基于css的卡通片,不仅仅更快;也不会被大量的js统计所阻塞。

 

最后

事先有线支付时,半数以上人都很欣赏使用 translateZ(0)
来拓展所谓的硬件加速,以升级品质,不过品质优化并不曾所谓的“银弹”,translateZ(0)
不是,本文列出的优化提议也不是。抛开了对页面的具体分析,任何的特性优化都是站不住脚的,盲目标选拔一些优化措施,结果或者会事与愿违。因而具体的去分析页面的莫过于品质表现,不断的查对测试,才是不错的优化途径。

优化技术计算

  • 压缩浏览器的重排和重绘的发生。
  • 永不拔取table布局。
  • css动画中尽量只利用transform和opacity,那不会发出重排和重绘。
  • 尽可能地只利用css做动画。
  • 防止浏览器的隐式合成。
  • 转移复合层的尺寸。

浏览器什么日期会创建一个单独的复合图层呢?事实上一般是在偏下二种意况下:

参考

  • PaintLayer.h
  • PaintLayer.cpp
  • CompositingReasons.cpp
  • CompositingReasons.h
  • CompositingRequirementsUpdater.cpp
  • chrome layout
    test
  • Slimming Paint
  • The stacking
    contest
  • Blink Compositing Update: Recap and
    Squashing
  • GPU Accelerated Compositing in
    Chrome
  • CSS Triggers
  • google render
    performance

    1 赞 6 收藏
    评论

亚洲必赢官网 38

参考

GPU合成首要参考:

https://www.smashingmagazine….

什么样属性会唤起reflow、repaint及composite,你可以在这么些网站找到:

1 赞 2 收藏
评论

亚洲必赢官网 39

3D 或者 CSS transform

<video> 和 <canvas> 标签

CSS filters

要素覆盖时,比如动用了 z-index 属性

 

4并不是颇具的CSS属性都能触发GPU的硬件加快,实际上唯有个别品质可以,比如上面的这几个:

transform

opacity

filter

 

 

5.什么样在桌面端和移动端用CSS开启硬件加快

CSS animations, transforms 以及 transitions
不会自行开启GPU加快,而是由浏览器的迟缓的软件渲染引擎来施行。那大家怎么才得以切换来GPU形式吧,很多浏览器提供了一些触发的CSS规则。

近日,像Chrome, FireFox, Safari,
IE9+和新型版本的Opera都支持硬件加快,当它们检测到页面中某个DOM元素采取了某些CSS规则时就会敞开,最引人注目的特性的元素的3D变换。

例如:

.cube {

   -webkit-transform: translate3d(250px,250px,250px)

   rotate3d(250px,250px,250px,-120deg)

   scale3d(0.5, 0.5, 0.5);

}

而是在局地情景下,大家并不要求对元素选用3D变换的效果,那怎么做呢?那时候大家可以利用个小技巧“欺骗”浏览器来开启硬件加快。

就算如此大家或许不想对元素选取3D更换,可大家一样可以敞开3D引擎。例如大家可以用transform:
translateZ(0); 来开启硬件加速 。

.cube {

   -webkit-transform: translateZ(0);

   -moz-transform: translateZ(0);

   -ms-transform: translateZ(0);

   -o-transform: translateZ(0);

   transform: translateZ(0);

   /* Other transform properties here */

}

在 Chrome and Safari中,当大家应用CSS transforms 或者
animations时或者会有页面闪烁的听从,下边的代码可以修复此意况:

.cube {

   -webkit-backface-visibility: hidden;

   -moz-backface-visibility: hidden;

   -ms-backface-visibility: hidden;

   backface-visibility: hidden;

   -webkit-perspective: 1000;

   -moz-perspective: 1000;

   -ms-perspective: 1000;

   perspective: 1000;

   /* Other transform properties here */

}

在webkit内核的浏览器中,另一个有效的法门是

.cube {

   -webkit-transform: translate3d(0, 0, 0);

   -moz-transform: translate3d(0, 0, 0);

   -ms-transform: translate3d(0, 0, 0);

   transform: translate3d(0, 0, 0);

  /* Other transform properties here */

}

原生的位移端应用(Native mobile
applications)总是可以很好的利用GPU,那是为何它比网页应用(Web
apps)表现更好的原故。硬件加快在移动端更加有用,因为它可以使得的滑坡资源的选取(移动端本身资源有限)。

 

6.利用硬件加速的题材

行使硬件加速并不是十全十美的业务,比如:

1内存。即便GPU加载了大气的纹路,那么很简单就会发出内容难点,那点在运动端浏览器上进一步显著,所以,一定要记住不要让页面的每个元素都采取硬件加快。

2利用GPU渲染会影响字体的抗锯齿效果。那是因为GPU和CPU具有差其他渲染机制。即便最后硬件加快停止了,文本依旧会在动画期间显得得很模糊。

 

总结

只对咱们须求达成动画效果的元素运用以上措施,假若单纯为了打开硬件加快而不论乱用,这是不明智的。

小心使用这个措施,如若通过你的测试,结果确是抓好了质量,你才足以动用那些方法。使用GPU可能会造成惨重的性质难题,因为它扩张了内存的应用,而且它会削减活动端设备的电池寿命。

 

网站地图xml地图