浅析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/

原文地址:https://www.cnblogs.com/goloving/p/14978490.html