用CSS开启硬件加快来增加网站品质,css3硬件加快

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

2017/01/10 · CSS ·
AR

原稿出处: 黑古铜色的影子   

深信广大人在做运动端动画的时候蒙受了卡顿的难点,那篇小说尝试从浏览器渲染的角度;一点一点告诉你动画优化的规律及其技术,作为你办事中优化动画的参考。文末有优化技术的统计。

因为GPU合成没有合法正规,各个浏览器的题材和化解办法也不比;所以小说内容仅供参考。

有线质量优化:Composite

2016/04/26 · 基本功技术 ·
美高梅开户网址,无线

初稿出处: 天猫商城前端团队(FED)-
冬萌   

美高梅开户网址 1

1个 Web 页面的体现,不难的话可以认为经历了以下下多少个步骤。

美高梅开户网址 2

  • JavaScript:一般的话,大家会采纳 JavaScript
    来已毕部分视觉变化的功用。比如做一个动画片只怕往页面里添加一些 DOM
    成分等。
  • Style:总括样式,那个历程是基于 CSS 选用器,对种种 DOM
    成分匹配对应的 CSS 样式。这一步为止之后,就确定了每种 DOM
    成分上该采用什么 CSS 样式规则。
  • Layout:布局,上一步确定了每种 DOM
    成分的体制规则,这一步就是具体测算逐个 DOM
    成分最后在显示器上显得的轻重缓急和岗位。web
    页面中成分的布局是对峙的,由此二个成分的布局爆发变化,会联动地吸引其余因素的布局发生变化。比如,“
    成分的小幅的变通会潜移默化其子成分的宽度,其子成分宽度的变更也会一连对其孙子成分爆发潜移默化。因而对此浏览器来说,布局进程是平常发出的。
  • Paint:绘制,本质上就是填充像素的经过。包罗绘制文字、颜色、图像、边框和影子等,约等于壹个DOM 成分所有的可视效果。一般的话,这一个绘制进度是在多个层上形成的。
  • Composite:渲染层合并,由上一步可知,对页面中 DOM
    成分的绘图是在多少个层上开展的。在各种层上完成绘制进度之后,浏览器会将所有层依据客观的次第合并成多少个图层,然后展以往显示器上。对于有义务重叠的因素的页面,这些进程尤其重点,因为借使图层的联合顺序出错,将会招致成分展现万分。

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

1. 何为硬件加快

卡通卡顿是在活动web开发时平日遇上的题材,消除这么些题材一般会用到css3硬件加快
css3硬件加速那一个名字感觉上很伟大上,其实它做的事务可以简单概括为:通过GPU进行渲染,解放cpu。

浏览器渲染

增强动画的优化不得不提及浏览器是怎么渲染二个页面。在从服务器中拿到多少后,浏览器会先做分析三类东西:

  • 解析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会将各层合成;彰显在屏幕上。

浏览器渲染原理

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

注:由于 Chrome 对 Blank
引擎某个已毕的修改,有个别大家从前熟稔的类名有了变动,比如 RenderObject
变成了 LayoutObject,RenderLayer 变成了 PaintLayer。感兴趣的看以参阅
Slimming Paint。

在浏览器中,页面内容是储存为由 Node 对象组成的树状结构,也等于 DOM
树。每1个 HTML element 成分都有3个 Node 对象与之相应,DOM
树的根节点永远都是 Document Node。那或多或少相信大家都很熟识了,但其实,从
DOM 树到结尾的渲染,需求进行部分变换映射。

美高梅开户网址 3

就是将浏览器的渲染进程交给GPU处理,而不是行使自带的相比较慢的渲染器。这样就足以使得animation与transition越发顺畅。

现象

经过对照不使用css3加速和使用css3加速三个例证,大家得以看来双方渲染的出入:

美高梅开户网址 4

不使用css3加速.png

美高梅开户网址 5

使用css3加速.png

前端通过改动top和left天性举办动画,fps维持在47左右,cpu一向进展测算;后者通过transform落实,fps在62左右,cpu基本不须求统计。相比较可以通过transform不光荣升了渲染品质,也解放了cpu。

渲染优化原理

如上所说,渲染树打造完毕后;浏览器要做的步骤:

reflow——》repaint——》composite

从 Nodes 到 LayoutObjects

DOM 树中得每一种 Node 节点都有二个一见如旧的 LayoutObject 。LayoutObject
知道什么在显示器上 paint Node 的故事情节。

咱俩得以在浏览器中用css开启硬件加快,使GPU (Graphics Processing Unit)
发挥效果,从而升级品质

原理

DOM树和CSS结合后形成渲染树。渲染树中含有了汪洋的渲染成分,每3个渲染成分会被分到贰个图层中,每种图层又会被加载到GPU形成渲染纹理。GPU中transform是不会触发
repaint 的,这点卓殊类似3D绘图功效,最后那些使用
transform的图层都会由独立的合成器进度展开拍卖。

经过chrome的timeline工具,栗褐框代表须要repaint的一对,玉米黄框代表渲染图层,相比较两者可见采取的css3硬件加快后,不会举办repaint操作,而只会时有爆发2个渲染图层,GPU就背负操作那个渲染图层。

美高梅开户网址 6

不使用css3加速.png

美高梅开户网址 7

使用css3加速.png

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)。然后做大量的改动后,再把它显得出来。
    • clone1个dom节点在内存里,修改以后;与在线的节点相替换。
  • 不要采纳table布局,1个小改变会导致整个table的重复布局。
  • transform和opacity只会唤起合成,不会唤起布局和重绘。

从上述的拔尖实践中你大概发现,动画优化一般都以尽量地压缩reflow、repaint的暴发。关于如何属性会引起reflow、repaint及composite,你可以在这些网站找到。

从 LayoutObjects 到 PaintLayers

诚如的话,拥有相同的坐标空间的
LayoutObjects,属于同1个渲染层(PaintLayer)。PaintLayer 最初是用来兑现
stacking
contest(层叠上下文),以此来保管页面成分以正确的逐一合成(composite),那样才能科学的显得成分的交汇以及半透明成分等等。因而知足形成层叠上下文条件的
LayoutObject
一定会为其创设新的渲染层,当然还有其余的有个别特殊境况,为一些特殊的
LayoutObjects 创立2个新的渲染层,比如 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,比如1个一直不视觉属性(背景、颜色、阴影等)的空 div。

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

现行多数电脑的显卡都协理硬件增加速度。鉴于此,我们得以表明GPU的能力,从而使大家的网站或应用表现的更是流畅。

复合图层

在常理中我们关系transform会成立1个图层,GPU会来施行transform的操作,这么些图层且称为复合图层(composited
layer)。
即使 Chrome
的启发式方法(heuristic)随着时光在相连发展前行,不过从近期的话,满意以下任意景况便会创立层:

  • 3D 或透视变换(perspective transform) CSS 属性
  • 运用加快视频解码的因素,如<video>
  • 具备 3D (WebGL) 上下文或加紧的 2D 上下文的要素,如<canvas>
  • 错落插件(如 Flash)
  • 对协调的 opacity 做 CSS 动画或利用四个动画片 webkit 变换的因素
  • 所有加速 CSS 过滤器的成分,如CSS filters
  • 要素有3个分包复合层的后人节点(换句话说,就是3个因素拥有三个子成分,该子成分在自身的层里)
  • 要素有1个 z-index
    较低且含有1个复合层的兄弟成分(换句话说就是该因素在复合层下边渲染)

只要页面建立了过多的复合图层,同样也会导致页面的卡顿。在CSS3硬件加速也有坑那篇文章中,作者介绍了是因为z-index造成复合图层过多而吸引的题材,在随后开发时得以借鉴。可以调节图层过多卡顿页面问询z-idnex对图层创制的影响。

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属性,做3个运动动画:

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开启硬件加快来增加网站品质,css3硬件加快。不予赖文档流。
  • 不会招致重绘。

满意以上以上条件的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动画的一对题材。

从 PaintLayers 到 GraphicsLayers

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

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

渲染层升高为合成层的原委有弹指间两种:

注:渲染层升高为合成层有七个先决条件,该渲染层必须是
SelfPaintingLayer(基本可认为是上文介绍的
NormalPaintLayer)。以下所谈论的渲染层提高为合成层的场所都以在该渲染层为
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美高梅开户网址 9
    • 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
    重叠原因为啥会因为重叠原由此发出合成层呢?举个几乎的板栗。美高梅开户网址 10森林绿的矩形重叠在浅橙矩形之上,同时它们的父成分是三个GraphicsLayer。此时只要古铜黑矩形为二个 GraphicsLayer,假若 overlap
    不可以提拔合成层的话,那么鲜紫矩形不会升级为合成层,也就会和父元素公用一个GraphicsLayer。美高梅开户网址 11那会儿,渲染顺序就会发生错误,由此为力保渲染顺序,overlap
    也变成了合成层暴发的缘由,也等于之类的正规意况。美高梅开户网址 12理所当然
    overlap 的由来也会细分为几类,接下去大家会详细看下。

    • 臃肿恐怕说部分重叠在1个合成层之上。那怎么终归重叠呢,最广大和简单驾驭的就是因素的
      border box(content + padding + border)
      和合成层的有臃肿,比如:demo,当然
      margin area
      的重叠是行不通的(demo)。其余的还有一对不普遍的意况,也终归同合成层重叠的尺度,如下:

      • filter 效果同合成层重叠
        demo
      • transform 变换后同合成层重叠
        demo
      • overflow scroll 意况下同合成层重叠。即如果二个 overflow
        scroll(不管 overflow:auto 还是
        overflow:scrill,只假诺能 scroll 即可)
        的成分同2个合成层重叠,则其可视子成分也同该合成层重叠
        demo
    • 只要重叠在壹个合成层之上(assumedOverlap)。这么些缘故听上去有点虚,什么叫假使重叠?其实也相比较好精晓,比如壹个要素的
      CSS
      动画功用,动画运营时期,成分是有大概和其余因素有重叠的。针对于那种场馆,于是就有了
      assumedOverlap
      的合成层暴发原因,示例可知:demo。在本
      demo 中,动画成分视觉上并不曾和其兄弟成分重叠,但因为
      assumedOverlap
      的来由,其兄弟成分依然进步为了合成层。须求专注的是该原因下,有三个很万分的事态:假若合成层有内联的
      transform 属性,会招致其兄弟渲染层 assume
      overlap,从而进步为合成层。比如:demo。

2硬件加速原理

启用

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

  • transform
  • opacity
  • filter
  • will-change:哪二个属性即将暴发变化,进而进行优化。

地点的的例子中用到的是transform
2D,它是在运作时才会创建图层,由此在动画起始和停止时会进行repaint操作;而浏览器在渲染前就为transform
3D创设了图层。

美高梅开户网址 13

千帆竞发时的repaint

美高梅开户网址 14

终结时的repaint

可以由此transform的3D属性强制开启GPU加快:

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

GPU是如何合成图像的

GPU实际上可以看作二个单身的处理器,它有温馨的处理器和存储器及数据处理模型。当浏览器向GPU发送音信的时候,似乎向3个外部设备发送消息。

您可以把浏览器向GPU发送数据的进程,与应用ajax向服务器发送新闻万分相近。想转手,你用ajax向服务器发送数据,服务器是不会直接收受浏览器的贮存的新闻的。你需求收集页面上的数码,把它们放进贰个载体里面(例如JSON),然后发送数据到长途服务器。

相同的,浏览器向GPU发送数据也亟需先成立一个载体;只不过GPU距离CPU很近,不会像远程服务器那样只怕几千里那么远。不过对于远程服务器,2秒的延期是还行的;可是对于GPU,几微秒的推移都会造成动画的卡顿。

浏览器向GPU发送的数额载体是怎么样?那里给出2个归纳的制作载体,并把它们发送到GPU的经过。

  • 画每种复合层的图像
  • 桑土绸缪图层的数目
  • 预备动画的着色器(即使必要)
  • 向GPU发送数据

之所以您可以观看,每一次当你添加transform:translateZ(0)will-change:transform给三个因素,你都会做相同的做事。重绘是相当消耗品质的,在此地它特别缓慢。在多数意况,浏览器不大概增量重绘。它只好重绘先前被复合层覆盖的区域。

层压缩

大多周边的有个别合成层的升高原因如上所说,你会发觉,由于重叠的原委,大概轻易就会生出出大气合成层来,而各种合成层都要耗费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

浏览器接收到页面文档后,会将文档中的标记语言分析为DOM树。DOM树和CSS结合后形成浏览器创设页面的渲染树。渲染树中隐含了大气的渲染成分,每1个渲染成分会被分到七个图层中,各种图层又会被加载到GPU形成渲染纹理,而图层在GPU中transform 是不会触发
repaint
的,最后这么些应用 transform 的图层都会由单独的合成器进程展开拍卖。

注意事项
  • 无法让各类成分都启用硬件加快,那样会暂用很大的内存,使页面会有很强的卡顿感。
  • GPU渲染会潜移默化字体的抗锯齿效果。那是因为GPU和CPU具有区其余渲染机制,即便最后硬件加快为止了,文本依然会在动画时期显得得很模糊。

隐式合成

还记得刚才a成分和b成分动画的例证吗?以后大家将b成分做动画,a成分静止不动。

美高梅开户网址 18

和刚刚的例子分歧,以后b成分将具有贰个单身复合层;然后它们将被GPU合成。但是因为a成分要在b成分的方面(因为a元素的z-index比b成分高),那么浏览器会做什么样?浏览器会将a成分也单独做多个复合层!

之所以大家未来有多少个复合层a成分所在的复合层、b成分所在的复合层、其余情节及背景层。

3个或八个尚未协调复合层的成分要出新在有复合层成分的上边,它就会具有和谐的复合层;那种状态被叫作隐式合成。

浏览器将a成分进步为二个复合层有很两种缘由,上面罗列了有个别:

  • 3d或透视变换css属性,例如translate3d,translateZ等等(js一般通过那种方法,使成分得到复合层)
  • <video><iframe><canvas><webgl>等元素。
  • 掺杂插件(如flash)。
  • 要素本身的 opacity和transform 做 CSS 动画。
  • 装有css过滤器的因素。
  • 使用will-change属性。
  • position:fixed。
  • 要素有两个 z-index
    较低且带有三个复合层的汉子儿成分(换句话说就是该因素在复合层上边渲染)

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

怎样查看合成层

行使 Chrome DevTools 工具来查阅页面中合成层的状态。

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

美高梅开户网址 19

里面,页面上的合成层会用深桔黄边框框出来。

美高梅开户网址 20

自然,越发详细的新闻可以透过 Timeline 来查看。

每多个独自的帧,看到种种帧的渲染细节:

美高梅开户网址 21

点击之后,你就会在视图中见到多少个新的选项卡:Layers。

美高梅开户网址 22

点击那么些 Layers
选项卡,你会看到多少个新的视图。在那么些视图中,你可以对这一帧中的所有合成层举行扫描、缩放等操作,同时还可以见到各类渲染层被创立的案由。

美高梅开户网址 23

有了那些视图,你就能掌握页面中终归有多少个合成层。假设您在对页面滚动或渐变效果的质量分析中窥见
Composite
进程用度了太多时光,那么您可以从这么些视图里看到页面中有多少个渲染层,它们为啥被成立,从而对合成层的多寡举行优化。

CSS transform 会创制了壹个新的复合图层,能够被GPU直接用来执行 transform 操作。

参照小说:
  1. CSS动画之硬件加快:作者比较详细介绍了硬件加快,计算的很成功。
  2. CSS3硬件加快也有坑:
    作者介绍了由于z-index造成复合图层过多,未来开发加以注意。
  3. 利用CSS3
    will-change提升页面滚动、动画等渲染品质:
    will-change的介绍
  4. javascript品质优化-repaint和reflow:质量刀客以及优化措施。
  5. 两张图解释CSS动画的属性:比较详细相比了运用硬件加快和不使用硬件加快的流水线差别。

内存占用

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

一个渲染层,须要多少内存占用?为了方便驾驭,举二个回顾的例子;1个宽、高都以300px的纯色图像要求多少内存?

300 300 4 =
350000字节,即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帧,动画平滑、流畅。
  • 三个适宜的卡通片工作在2个独门的线程,它不会被多量的js统计阻塞。
  • 3D“变换”是便利的。

缺点:

  • 升高2个因素到复合层要求万分的重绘,有时那是慢的。(即大家收获的是一个全层重绘,而不是多少个增量)
  • 绘图层必须传输到GPU。取决于层的数额和传导恐怕会相当缓慢。那说不定让2个成分在初级设备上闪耀。
  • 各种复合层都须求消耗额外的内存,过多的内存只怕导致浏览器的崩溃。
  • 假定你不考虑隐式合成,而利用重绘;会招致额外的内存占用,并且浏览器崩溃的票房价值是尤其高的。
  • 我们会有视觉假象,例如在Safari中的文本渲染,在好几景况下页面内容将消灭或变形。

进步动画效果的要素

合成层的补益是不会潜移默化到其余因素的绘图,由此,为了减小动画成分对任何因素的影响,从而收缩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

对此那1个近年来还不支持 will-change 属性的浏览器,近年来常用的是应用1个 3D
transform 属性来强制提高为合成层:

CSS

#target { transform: translateZ(0); }

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

但需求注意的是,不要创设太多的渲染层。因为每创制三个新的渲染层,就代表新的内存分配和更复杂的层的管制。之后大家会详细切磋。

若是你已经把三个成分放到一个新的合成层里,那么可以行使 Timeline
来确认这么做是或不是真正立异了渲染品质。别盲目提高合成层,一定要分析其实际品质表现。

  • 3D 或者 CSS transform
  • <video> 和 <canvas> 标签
  • CSS filters
  • 要素覆盖时,比如采取了 z-index 属性

优化技术

采取 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属性,成分上有了那脾特性,浏览器会升高这几个因素变为1个复合层(不是一连)。那样动画就足以平滑的初步和终结。可是不用滥用那特个性,否则会大大增加内存消耗。

削减绘制区域

对此不必要再行绘制的区域应尽量避免绘制,以收缩绘制区域,比如三个 fix
在页面顶部的定势不变的导航 header,在页面内容某些区域 repaint
时,整个显示屏包涵 fix 的 header 也会被重绘,见
demo,结果如下:

美高梅开户网址 30

而对于平昔不变的区域,我们期待其并不会被重绘,因而可以透过事先的方法,将其晋级为单身的合成层。

减去绘制区域,要求精心分析页面,区分绘制区域,裁减重绘区域甚至防止重绘。

3 为何硬件加快会使页面流畅

动画中只行使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>

客观管理合成层

看完上边的稿子,你会意识进步合成层会达到更好的属性。那看起来越发诱人,不过难题是,创立1个新的合成层并不是免费的,它得消耗额外的内存和治本财富。实际上,在内存能源有限的装置上,合成层带来的性情改良,恐怕远远赶不上过多合成层开销给页面质量带来的负面影响。同时,由于各类渲染层的纹理都亟待上传到
GPU 处理,由此大家还索要考虑 CPU 和 GPU 之间的带宽难点、以及有多大内存供
GPU 处理那么些纹理的题材。

对于合成层占用内存的难题,大家大概做了多少个 demo 进行了求证。

demo
1
和 demo
2
中,会创建 三千 个相同的 div 成分,不一致的是 demo
2
中的成分通过 will-change 都升高为了合成层,而多个 demo
页面的内存消耗却有很醒目标反差。

美高梅开户网址 31

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

减小复合层的尺码

看一下两张图片,有如何差距吧?

美高梅开户网址 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将它们放大;用户不汇合到什么不一致,可是你可以削减大气的仓储空间。

提防层爆炸

经过事先的介绍,大家清楚同合成层重叠也会使成分进步为合成层,就算有浏览器的层压缩编制,但是也有众多不只怕进展削减的情况。相当于说除了我们显式的扬言的合成层,还或者出于重叠原因不经意间爆发一些不在预期的合成层,极端一点可能会发生大量的额外合成层,出现层爆炸的情景。我们差不多写了2个无限点但实在在大家的页面中相比常见的
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

那时候,由于第1个 .box 因为 squashingLayerIsAnimating
的来由无法回落,其余的都被核减到了一块儿。

美高梅开户网址 36

并且,内存占用相比从前也暴跌了不少。

美高梅开户网址 37

怎么 transform 没有触发 repaint 呢?一言以蔽之,transform
动画由GPU控制,协助硬件加速,并不须要软件方面的渲染。

用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, Fire福克斯, 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地图