(一)前言

在需要高频交互的css动画时候,我们就需要考虑使用CSS3 硬件加速。

首先,CSS3 硬件加速又叫做 GPU 加速,是利用 GPU 进行渲染,
减少 CPU 操作的一种优化方案。由于 GPU 中的 transform 等 CSS
属性不会触发 repaint,所以能大大提高网页的性能。

现在,像Chrome, FireFox, Safari, IE9+和最新版本的Opera都支持硬件加速,当它们检测到页面中某个DOM元素应用了某些CSS规则时就会开启,最显著的特征的元素的3D变换。

(二)案例分析
首先我们来实现一个小球动画,我们先用left和top来控制位置,然后查看其丢帧情况,然后我们再使用transform来实现一样的效果, 然后对比两次的性能报告

我们先给源码吧

这是通过left和top实现位移

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>CSS动画left</title>
  <style>
    body {
      padding: 30px;
      text-align: center;
    }

    .container {
      position: relative;
      min-height: 400px;
      -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
      margin: auto;
    }

    .item {
      position: absolute;
      top: 0;
      left: 0;
      width: 100px;
      height: 100px;
      border-radius: 50%;
      box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.75);
    }

    .item-running {
      animation: run-around 4s infinite;
    }

    @keyframes run-around {
      0% {
        top: 0;
        left: 0;
      }

      25% {
        top: 0;
        left: 200px;
      }

      50% {
        top: 200px;
        left: 200px;
      }

      75% {
        top: 200px;
        left: 0;
      }
    }
  </style>
</head>
<body>
<div class="container">
  <div class="item item-running"></div>
</div>

</body>
</html>

这是通过translate实现位移

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>CSS动画-硬件加速translate</title>
  <style>
    body {
      padding: 30px;
      text-align: center;
    }

    .container {
      min-height: 400px;
      -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
      margin: auto;
    }

    .item {
      width: 100px;
      height: 100px;
      border-radius: 50%;
      box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.75);
    }

    .item-running {
      animation: run-around 4s infinite;
    }

    @keyframes run-around {
      0% {
        transform: translate3d(0, 0, 0);
      }

      25% {
        transform: translate3d(200px, 0, 0);
      }

      50% {
        transform: translate3d(200px, 200px, 0);
      }

      75% {
        transform: translate3d(0, 200px, 0);
      }
    }
  </style>
</head>
<body>
<div class="container">
  <div class="item item-running"></div>
</div>
</body>
</html>

代码就是上面,现在我们来看两个的丢帧情况

CSS3 gpu css3 gpu加速_CSS

 我们可以看到因为left和top属性会导致重绘,导致rending,而且每一个步骤都有绿色柱状图,这是一个性能代价很高的操作,也是产生丢帧的关键。而transform会直接使用硬件加速,在GPU中运行,绕开了软件渲染。

(三)硬件加速原理

浏览器首先页面解释成DOM输,DOM树和CSS让浏览器构建渲染树,渲染书包含渲染对象 - 在页面中需要渲染的元素,每一个渲染对象被分配到一个图层中,每一个图层被更新到GPU,这里的秘诀就在于通过transform的层会使用GPU渲染,因此不需要重绘,就像3D图形一样。这个转换是单独处理的。

当然,浏览器创建这种层级的条件有以下几种

        1.3D 或者 CSS的transform属性
        2.<video>和 <canvas>元素
        3.CSS的filter属性
        4.覆盖在其它元素之上的元素,比如通过z-index提升层级

自然,不是所有的CSS都会在GPU执行,目前支持是以下几种

        1.transform
        2.opacity
        3.filter
因此,如果你动画,考虑性能,建议用以上CSS3来实现。

(四)开启硬件加速

可是在一些情况下,我们并不需要对元素应用3D变换的效果,那怎么办呢?这时候我们可以使用个小技巧“欺骗”浏览器来开启硬件加速(transform hack)。

虽然我们可能不想对元素应用3D变换,可我们一样可以开启3D引擎。例如我们可以用transform: translate3d(0, 0, 0); 来开启硬件加速 。

现在我们使用transform hack对上面修改left和top进行失帧情况

// 修改代码

// 将style里面的样式修改如下
.container {
      position: relative;
      min-height: 400px;
      -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
      margin: auto;
      transform: translate3d(0, 0, 0);
    }

对比图

CSS3 gpu css3 gpu加速_硬件加速_02

从图中我们可以看到,重绘的代价虽然变低,但是和直接时候transform还是差太多。

(五)注意事项

1.大部分重要的问题都是关于内存。GPU处理过多的内容会导致内存问题。这在移动端和移动端浏览器会导致崩溃。因此,通常不会对所有的元素使用硬件加速。
2.在GPU渲染字体会导致抗锯齿(-webkit-font-smoothing)无效。这是因为GPU和CPU的算法不同。因此即使最终硬件加速停止了,文本还是会在动画期间显示得很模糊。