受GPU限制的动画是否仍受CPU负载影响?

时间:2019-01-08 14:13:55

标签: javascript css css-animations

我已经使用以下样式为div创建了一个合成层:

div {
  position: absolute;
  height: 50px;
  width: 50px;
  background: #900;
  top: 100px;
  left: 200px;
  will-change: transform;
  transform: translateZ(0);
}

然后我使用Web动画API将动画应用到它:

document.getElementById("box").animate(
  [
    { transform: 'rotate(0) translate3D(-50%, -50%, 0)' },
    { transform: 'rotate(360deg) translate3D(-50%, -50%, 0)' }
  ], {
    duration: 500,
    iterations: Infinity
  }
);

根据我的理解,此动画现在由GPU处理,并且该层与其他层无关,因此GPU可以独立地对其进行操作,而不必担心计算页面其他部分的几何形状。 / p>

我不了解的是,如果我调用一个占用大量CPU资源的函数,该动画将在函数运行时完全停止,并在函数退出时再次出现:

function mySlowFunction(baseNumber) {
    console.time('mySlowFunction');
    var result = 0; 
    for (var i = Math.pow(baseNumber, 10); i >= 0; i--) {       
        result += Math.atan(i) * Math.tan(i);
    };
    console.timeEnd('mySlowFunction');
    return result;
}

setTimeout(() => mySlowFunction(5), 3000);

有什么办法可以防止这种情况?

https://jsfiddle.net/Lsmw85rv/4/

1 个答案:

答案 0 :(得分:1)

是的,它们仍然可能会受到CPU负载的影响。
update the rendering算法是事件循环的一部分,因此,如果您以某种方式阻止事件循环,那么也会阻止渲染。

现在,鼓励实施者在遇到长期运行的代码时"spin the event loop",以便UI仍然可以是响应式的(并且非js驱动的动画可以继续运行),但这只是鼓励,并且所有实施不要以同样的方式做。

例如,在我的Firefox上,我看不到脚本的任何速度减慢,甚至也看不到下面更具攻击性的速度,而在Chrome上,我可以清楚地看到渲染被阻止。

现在要避免这种情况,正如评论中提到的那样,真正的防弹解决方案是在第二个线程using a Web Worker中运行阻止脚本。

document.getElementById("box").animate(
  [{
      transform: 'rotate(0) translate3D(-50%, -50%, 0)'
    },
    {
      transform: 'rotate(360deg) translate3D(-50%, -50%, 0)'
    }
  ], {
    duration: 500,
    iterations: Infinity
  }
);

function mySlowFunction(baseNumber) {
  console.time('mySlowFunction');
  const now = performance.now();
  while (performance.now() - now < baseNumber * 1000);
  console.timeEnd('mySlowFunction');
}

setTimeout(() => mySlowFunction(3), 3000);
#box {
  position: absolute;
  height: 50px;
  width: 50px;
  background: #900;
  top: 100px;
  left: 200px;
  will-change: transform;
  transform: translateZ(0);
}
<div id="box"></div>