CSS关键帧动画CPU使用率很高,应该这样吗?

时间:2012-11-01 12:08:33

标签: css3

我在几个元素上使用以下关键帧动画:

@keyframes redPulse {
    from { background-color: #bc330d; box-shadow: 0 0 9px #333; }
    50% { background-color: #e33100; box-shadow: 0 0 18px #e33100; }
    to { background-color: #bc330d; box-shadow: 0 0 9px #333; }
}
@-webkit-keyframes redPulse {
    from { background-color: #bc330d; box-shadow: 0 0 9px #333; }
    50% { background-color: #e33100; box-shadow: 0 0 18px #e33100; }
    to { background-color: #bc330d; box-shadow: 0 0 9px #333; }
}
.event_indicator {
    display: inline-block;
    background-color: red;
    width: 5px;
    margin-right: 5px;

    -webkit-animation-name: redPulse;
    -webkit-animation-duration: 1s;
    -webkit-animation-iteration-count: infinite;

    animation-name: redPulse;
    animation-duration: 1s;
    animation-iteration-count: infinite;
}

在我的计算机上,我在Chrome和Firefox中的CPU使用率大约为40%。 它是动画的当前状态(很好但现在不可用)或者我错过了一些魔法属性?

您可以使用相同的动画检查以下示例: http://jsfiddle.net/Nrp6Q/

5 个答案:

答案 0 :(得分:66)

是的,这是正常的,因为您在页面上有几个无限循环动画。因此,在渲染这些元素时,CPU会不断地工作。有一个“魔术”属性将显着降低CPU使用率,即:

transform: translateZ(0);

这会将元素合成到他们自己的图层中(通过欺骗浏览器认为它将进行3D变换),并且在大多数情况下,浏览器应该利用GPU加速,减轻CPU的负担。对我来说,这减少了大约20%(几乎一半)。

要了解有关此技术的更多信息,请查看:http://ariya.blogspot.com/2011/07/fluid-animation-with-accelerated.html

此外,动画中的关键帧越多,它也会越多。只需尝试剪掉中间关键帧的动画,你就会看到CPU使用量的另一个实质性下降(~10-12%)。

最后,并非所有属性都相同 - 框架阴影对于浏览器来说比使用背景颜色更加平滑地制作动画要困难得多。保留所有关键帧但保留box-shadow属性,使用translateZ(0)技巧使我的CPU使用率仅徘徊在10-11%。

尽管我很难说这一点,但对于无限循环动画,动画.gif在浏览器动画的当前状态下会比CSS3表现得更好,特别是如果您计划保留其中许多动画在页面上呈现了一段时间。

2017年更新:

对于那些仍在寻找问答方法的人来说,translate3d(0, 0, 0)提供与translateZ(0)相同的好处,您只需在translateX()设置translateY()translate3d(X, Y, Z)。同时。请@Farside忽略评论,因为他在演示中使用了translate(X, Y),但未将其与transform: rotateZ(360deg)进行比较,这表明使用此技术仍会产生显着差异。

根据this question,有些人发现所有浏览器(尤其是Chrome)的效果都更好{{1}}。

答案 1 :(得分:13)

减少CPU负载的一种可能方法是使用所谓的null transform hack,它通常被称为银弹。在许多情况下,它将极大地提高WebKit和Blink浏览器(如Chrome,Opera和Safari)的渲染性能。

“Null变换黑客”(硬件合成模式)

的用法

null变换hack基本上做了两件事:

  1. 启用硬件合成模式(假设平台支持)
  2. 它创建一个具有自己的背景表面
  3. 的新图层

    要“强制”浏览器,只需将其中一个CSS属性添加到元素中:

    transform: translateZ(0);
    
    /* or its friend: */
    transform: translate3d(0, 0, 0);
    

    使用3D变换时,最好还拥有这些属性to improve the performance

    backface-visibility: hidden;
    perspective: 1000;
    

    “null tr​​ansform hack”的注意事项

    在CSS3中为许多对象启用硬件加速可能会降低性能! 显然,每个零3D变换都会创建一个新图层。但是,强制黑客层创建可能并不总是解决页面上某些性能瓶颈的问题。层创建技术可以提高页面速度,但它们需要成本:它们占用系统RAM和GPU上的内存。因此,即使GPU做得很好,许多对象的传输可能也是一个问题,因此使用GPU加速可能不值得。引自W3C

      

    但是,在新图层中设置元素是一项相对昂贵的操作,可以将变换动画的开始延迟一小段时间。

    移动一些大型物体比使用3D加速时移动大量小物品具有更高的性能。因此,必须明智地使用,并且您需要确保硬件加速操作将真正有助于页面的性能,并且性能瓶颈不是由页面上的其他操作引起的。

    此外,GPU专门用于执行复杂的数学/几何计算,而将操作卸载到 GPU上会产生大量功耗。显然,当硬件启动时,目标设备的电池也会启动。

    现代方式:will-change属性

    进展不是站在一个地方...... W3C引入了will-change CSS属性。简而言之,will-change属性允许您提前通知浏览器您可能对元素进行哪些类型的更改,以便它可以在它们出现之前设置适当的优化需要的。

    以下是他们在draft中所说的内容:

      

    本规范中定义的will-change属性允许作者提前声明将来可能更改的属性,因此UA可以在需要之前的某个时间设置适当的优化。这样,当实际发生变化时,页面会以一种活泼的方式更新。

    使用will-change,向浏览器提示即将发生的转换可能就像将此规则添加到您希望转换的元素一样简单:

    will-change: transform;
    

    在开发移动设备时,开发人员在编写移动网络应用程序时不得不考虑各种设备限制。浏览器变得越来越聪明,有时,最好将决策留给平台本身,而不是重叠加速并以一种黑客的方式强制行为。

答案 2 :(得分:4)

在使用CSS3动画化一些元素时,我遇到了类似CPU使用率高的情况。我正在为~7个元素的“左”属性设置动画,在我的整个页面中使用了一些不透明度和阴影属性。我决定切换到jQuery.animate,遗憾的是根本没有提高性能。我的CPU(i7)在显示页面时仍然处于~9-15%,几个技巧(translateZ等)也没有真正改善性能 - 同时让我的布局搞砸了(一些绝对定位元素涉及,哎哟!)。

然后我偶然发现了这个奇妙的扩展:http://playground.benbarnett.net/jquery-animate-enhanced/

我只是引用了.js文件,没有在jQuery转换中进行单个更改,而且我的CPU使用率在同一页面上现在为1-2%。

我的建议:当使用CSS3过渡面临CPU问题时,请切换到jQuery + animate-enhanced-plugin。

答案 3 :(得分:2)

您还可以在要使用GPU而不是CPU

的任何以下类元素上使用它
.no-cpu {
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
    -ms-transform: translateZ(0);
}

<element class="event_indicator no-cpu">animation...</element >

答案 4 :(得分:1)

对于这里报道的“脉动”背景动画的特殊情况,我想出了一个css + js解决方案。

在我的情况下,背景动画是在background-position属性上,而不是在background-color上,但是原理是相同的。

好吧,假设您有一个具有特定背景的方块:

<div class="nice-block">...</div>

让我们设置样式:(scss)

.nice-block {
  background-color: red;
  //or it can be: background: linear-gradient(45deg, #red, #white, #red);
  //and:          background-size: 600% 600%;

  //the transform and will-change properties
  //are here to only enable GPU
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  -ms-transform: translateZ(0);
  will-change: transform;

  transition: background-color 5s ease;
  //if you want to add a pulsing effect 
  //to a gradient, see the following two lines:
  // background-position: 0% 50%!important;
  // transition: background-position 5s ease;

  &.animated {
    background-color: white;
    //and in case of gradient animation:
    // background-position: 100% 50%!important;
  }
}

现在是时候通过使用一些JavaScript向块添加“动画”类来实现效果了:

var bgAnimateTimer;
function animateBg () {
  clearTimeout(bgAnimateTimer);
  bgAnimateTimer = setTimeout(function () {
    clearTimeout(bgAnimateTimer);
    bgAnimateTimer = setTimeout(function () {

      document.querySelector('.nice-block').classList.toggle('animated');

      //jQuery alternative is:
      // $('.nice-block').toggleClass('animated');

      animateBg ();
    }, 5000); //5 seconds for the animation effect
  }, 2500); //2.5 seconds between each animation
}

animateBg ();

在我的案例中,这使性能提高了约15倍。

(i)注意,如果您想要的值与5秒不同,请在css和js中正确计算过渡和超时的秒数。