zoukankan      html  css  js  c++  java
  • CSS动画原理及硬件加速

    一、图层

      图层即层叠上下文,具体概念和应用大家可以看我之前转自张鑫旭大神博客的《CSS层叠上下文和层叠顺序》,这里我们简单复习一下产生层叠上下文的原因。

    1.根层叠上下文
      指的是页面根元素,也就是滚动条的默认的始作俑者<html>元素。这就是为什么,绝对定位元素在left/top等值定位的时候,如果没有其他定位元素限制,会相对浏览器窗口定位的原因。

    2.定位元素与传统层叠上下文
      对于包含有position:relative/position:absolute的定位元素,以及FireFox/IE浏览器(不包括Chrome等webkit内核浏览器)(目前,也就是2016年初是这样)下含有position:fixed声明的定位元素,当其z-index值不是auto的时候,会创建层叠上下文。

    3.CSS3与新时代的层叠上下文

      以下情况会产生新的层叠上下文:

    • 根元素(HTML)
    • 绝对或相对定位且 z-index 值不为 auto
    • 一个伸缩项目 Flex Item,且 z-index 值不为 auto,即父元素 display: flex|inline-flex
    • 元素的 opacity 属性值小于 1
    • 元素的 transform 属性值不为 none
    • 元素的 mix-blend-mode 属性值不为 normal
    • 元素的 filter 属性值不为 normal
    • 元素的 isolation 属性值为 isolate
    • position: fixed
    • will-change 中指定了上述任意属性,即便你没有直接定义这些属性
    • 元素的 -webkit-overflow-scrolling 属性值为 touch

    二、利用绝对定位+top/left实现动画

    CSS动画之硬件加速

      上图数据中的绿色条纹表示的就是使用 top 和 left 实现动画时浏览器发生的 repaint 操作,从中可以看出动画帧数远低于60 帧。

      从 chrome 的开发者工具按 ESC 之后选择 “rendering” 面板,我们可以通过选中“Enable piant flashing”来进一步监测 repaint 操作。开启该选项后,页面中的 repaint 区域就会被绿色蒙版高亮显示出来。重新使用 top 和 left 的示例演示的话,你会发现包裹球的那块区域会一直闪烁绿色的蒙版。

    CSS动画之硬件加速

      按照常理来说,改变元素位置会产生重排,为什么上面图中显示的全是重绘呢?原因是绝对定位会建立一个新的图层,而此图层上只有当前一个元素,多以只会重绘,而不会重排。这也告诉我们,在同一层中,元素数量少的情况下,重排性能对更好,速度会更快。

    三、transform2D实现动画

      下图是使用CSS transform 检测到的数据:

    CSS动画之硬件加速

      如你所见,动画演示期间并没有过多的 repaint 操作。

      那么,为什么 transform 没有触发 repaint 呢?简而言之,transform 动画由GPU控制,支持硬件加速,并不需要软件方面的渲染。

    四、硬件加速原理

      浏览器接收到页面文档后,会将文档中的标记语言解析为DOM树。DOM树和CSS结合后形成浏览器构建页面的渲染树。渲染树中包含了大量的渲染元素,每一个渲染元素会被分到一个图层中,每个图层又会被加载到GPU形成渲染纹理,而图层在GPU中transform 是不会触发 repaint 的,最终这些使用 transform 的图层都会由独立的合成器进程进行处理。

      在我们的示例中,CSS transform 创建了一个新的复合图层,可以被GPU直接用来执行 transform 操作。在chrome开发者工具中开启“show layer borders”选项后,每个复合图层就会显示一条黄色的边界:

      示例中的球就处于一个独立的复合图层,移动时的变化也是独立的:

    CSS动画之硬件加速

    此时,你也许会问:浏览器什么时候会创建一个独立的复合图层呢?事实上一般是在以下几种情况下:

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

    等一下,上面的示例使用的是 2D transition 而不是 3D 的 transforms 啊?这个说法没错,所以在timeline中我们可以看到:动画开始和结束的时候发生了两次 repaint 操作。

    CSS动画之硬件加速

      3D 和 2D transform 的区别就在于,浏览器在页面渲染前为3D动画创建独立的复合图层,而在运行期间为2D动画创建。动画开始时,生成新的复合图层并加载为GPU的纹理用于初始化 repaint。然后由GPU的复合器操纵整个动画的执行。最后当动画结束时,再次执行 repaint 操作删除复合图层。

    五、强制GPU渲染

      并不是所有的CSS属性都能触发GPU的硬件加速(图层在GPU中属性改变不会触发 repaint ),实际上只有少数属性可以,比如下面的这些:

    • transform
    • opacity
    • filter

      为了避免 2D transform 动画在开始和结束时发生的 repaint 操作,我们可以硬编码一些样式来解决这个问题:

    .example1 {
      transform: translateZ(0);
    }
    
    .example2 {
      transform: rotateZ(360deg);
    }

      这段代码的作用就是让浏览器执行 3D transform。浏览器通过该样式创建了一个独立图层,图层中的动画则有GPU进行预处理并且触发了硬件加速。

      如果某一个元素的背后是一个复杂元素,那么该元素的 repaint 操作就会耗费大量的资源,此时也可以使用上面的技巧来减少性能开销。

    六、使用硬件加速的问题

      使用硬件加速并不是十全十美的事情,比如:

    • 内存。如果GPU加载了大量的纹理,那么很容易就会发生内容问题,这一点在移动端浏览器上尤为明显,所以,一定要牢记不要让页面的每个元素都使用硬件加速。
    • 使用GPU渲染会影响字体的抗锯齿效果。这是因为GPU和CPU具有不同的渲染机制。即使最终硬件加速停止了,文本还是会在动画期间显示得很模糊。

    七、总结

      感觉这里面逻辑很乱,在这里整理一下。首先transform和绝对定位都会产生新的图层,所以都不存在重排,图层在GPU中transform又不会引起重绘,这就是硬件加速的原理。另外,transform3D和2D的区别在于3D渲染前便会产生新的图层,而2D是在运行时产生图层,运行结束时删除图层。

    注:本文在整理了南北在W3C上写的《CSS动画之硬件加速》中的知识点,并加入了自己的理解和总结

  • 相关阅读:
    十七:CSS之CSS继承和层叠
    十六:CSS之CSS选择器之后代选择器、伪类选择器
    十五:CSS之CSS选择器之群组选择器、全局选择器
    十四:CSS之CSS选择器之标签选择器、类选择器、ID选择器
    Android开发技巧——ViewPager加View情况封装PagerAdapter的实现类
    JAVA知识笔记
    机器学习笔记
    设计模式学习
    Android小知识汇总
    判断GPS是否开启&转到设置GPS界面
  • 原文地址:https://www.cnblogs.com/shytong/p/5419565.html
Copyright © 2011-2022 走看看