我已经使用以下样式为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);
有什么办法可以防止这种情况?
答案 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>