zoukankan      html  css  js  c++  java
  • 浅析CSS的性能优化:transform与position区别、硬件加速工作原理及注意事项、强制使用GPU渲染的友好CSS属性

      在网上看到一个这样的问题: transform与position:absolute 有什么区别?查阅资料后发现这道题目其实不简单,涉及到重排、重绘、硬件加速等网页优化的知识。

    一、问题背景

    过去几年,我们常常会听说硬件加速给移动端带来了巨大的体验提升,但是即使对于很多经验丰富的开发者来说,恐怕对其背后的工作原理也是模棱两可,更不要合理地将其运用到网页的动画效果中了著作权归作者所有。
    商业转载请联系作者获得授权,非商业转载请注明出处。
    原文: https://www.w3cplus.com/css3/introduction-to-hardware-acceleration-css-animations.html © w3cplus.com
    过去几年,我们常常会听说硬件加速给移动端带来了巨大的体验提升,但是即使对于很多经验丰富的开发者来说,恐怕对其背后的工作原理也是模棱两可,更不要合理地将其运用到网页的动画效果中了著作权归作者所有。
    商业转载请联系作者获得授权,非商业转载请注明出处。
    原文: https://www.w3cplus.com/css3/introduction-to-hardware-acceleration-css-animations.html © w3cplus.com

      过去几年,我们常常会听说硬件加速给移动端带来了巨大的体验提升,但是即使对于很多经验丰富的开发者来说,恐怕对其背后的工作原理也是模棱两可,更不要合理地将其运用到网页的动画效果中了。

    1、position + top/left 的效果

      下面让我们来看一个动画效果,在该动画中包含了几个堆叠在一起的球并让它们沿相同路径移动。最简单的方式就是实时调整它们的 left 和 top 属性,使用 css 动画实现。

    <style>
        html,
        body {
            width: 100%;
            height: 100%;
        }
        .ball-running {
            animation: run-around 4s infinite;
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
        }
        @keyframes run-around {
            0%: {
                top: 0;
                left: 0;
            }
            25% {
                top: 0;
                left: 200px;
            }
            50% {
                top: 200px;
                left: 200px;
            }
            75% {
                top: 200px;
                left: 0;
            }
        }
    </style>
    <body>
        <div class="ball-running"></div>
    </body>

      在运行的时候,即使是在电脑浏览器上也会隐约觉得动画的运行并不流畅,动画有些停顿的感觉,更不要提在移动端达到 60fps 的流畅效果了。这是因为top和left的改变会触发浏览器的 reflow 和 repaint ,整个动画过程都在不断触发浏览器的重新渲染,这个过程是很影响性能的。

    2、transform 的效果

      为了解决这个问题,我们使用 transform 中的 translate() 来替换 top 和 left ,重写一下这个动画效果。

    <style>
        html,
        body {
            width: 100%;
            height: 100%;
        }
        .ball-running {
            animation: run-around2 4s infinite;
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
        }
        @keyframes run-around2 {
            0%: {
                transform: translate(0, 0);
            }
            25% {
                transform: translate(200px, 0);
            }
            50% {
                transform: translate(200px, 200px);
            }
            75% {
                transform: translate(0, 200px);
            }
        }
    </style>
    <body>
        <div class="ball-running"></div>
    </body>

      这时候会发现整个动画效果流畅了很多,在动画移动的过程中也没有发生repaint和reflow。

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

    二、硬件加速工作原理

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

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

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

    (1)3D 或者 CSS transform

    (2)video或canvas标签

    (3)CSS filters

    (4)元素覆盖时,比如使用了 z-index 属性

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

      3D 和 2D transform 的区别就在于,浏览器在页面渲染前为3D动画创建独立的复合图层,而在运行期间为2D动画创建。

      动画开始时,生成新的复合图层并加载为GPU的纹理用于初始化 repaint,然后由GPU的复合器操纵整个动画的执行,最后当动画结束时,再次执行 repaint 操作删除复合图层。

    三、使用 GPU 渲染元素

    1、能触发GPU渲染的属性

      并不是所有的CSS属性都能触发GPU的硬件加速,实际上只有少数属性可以,比如下面的这些:

    (1)transform

    (2)opacity

    (3)filter

    2、强制使用GPU渲染

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

    .exam1{
        transform: translateZ(0);
    }
    .exam2{
        transform: rotateZ(360deg);
    }

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

    3、使用硬件加速需要注意的事项

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

    (1)内存。如果GPU加载了大量的纹理,那么很容易就会发生内存问题,这一点在移动端浏览器上尤为明显,所以,一定要牢记不要让页面的每个元素都使用硬件加速。

    (2)使用GPU渲染会影响字体的抗锯齿效果。这是因为GPU和CPU具有不同的渲染机制,即使最终硬件加速停止了,文本还是会在动画期间显示得很模糊。

    4、will-change

      浏览器还提出了一个 will-change 属性,该属性允许开发者告知浏览器哪一个属性即将发生变化,从而为浏览器对该属性进行优化提供了时间。下面是一个使用 will-change 的示例

    .exam3{
        will-change: transform;
    }

      缺点在于其兼容性不大好。

      总结:

    1、transform 会使用 GPU 硬件加速,性能更好;position + top/left 会触发大量的重绘和回流,性能影响较大。

    2、硬件加速的工作原理是创建一个新的复合图层,然后使用合成线程进行渲染。

    3、3D 动画 与 2D 动画的区别;2D动画会在动画开始和动画结束时触发2次重新渲染。

    4、使用GPU可以优化动画效果,但是不要滥用,会有内存问题。

    5、理解强制触发硬件加速的 transform 技巧,使用对GPU友好的CSS属性。

    英文原文:http://www.sitepoint.com/introduction-to-hardware-acceleration-css-animations/

  • 相关阅读:
    Java进阶(七)布隆过滤器
    NIO面试题
    TCP/IP面试题
    SPRING面试题
    SpringBoot(五)原理剖析:Transaction原理
    SpringBoot(四)原理剖析:AOP原理
    SpringBoot(三)原理剖析:IOC原理
    SpringBoot(二)原理剖析:AutoConfiguration原理
    mysql 安全更新
    查看端口占用
  • 原文地址:https://www.cnblogs.com/goloving/p/14978490.html
Copyright © 2011-2022 走看看