为什么阻止事件循环不阻止CSS动画?

为什么阻止事件循环不阻止CSS动画?

问题描述:

我不知道网页渲染的生命周期-因此在下面的示例中,我有两颗心-一颗是用js动画的,另一颗是用CSS动画的。当我用 alert 消息阻止事件循环时,CSS心仍然保持动画状态。

I do not know the webpage rendering lifecycle - so in the example below I have two hearts - one is animated by js and another one in CSS. When I block an event loop with an alert message, CSS heart remains animated.

let scale = true;
setInterval(() => {
  $('.animate-js').css('transform', `scale(${scale ? 1.4 : 1})`);
  scale = !scale;
}, 1000)

body {
  text-align: center;
}

.heart {
  white-space: nowrap;
  display: inline-block;
  font-size: 150px;
  color: #e00;
  transform-origin: center;
}

.animate-css {
  animation: beat 2s steps(2, end) infinite;
}


/* Heart beat animation */

@keyframes beat {
  to {
    transform: scale(1.4);
  }
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="heart">I
  <div class="animate-css heart">&#x2665;</div> CSS</div>
<div class="heart">I
  <div class="animate-js heart">&#x2665;</div> JS</div>
<br/>
<button onClick="alert('hurray!')">
I love it too
</button>

我很确定这是由于CSS动画是在javascript事件循环之外进行处理的事实,但我不是确定我的假设是否正确。最接近内部解释的文章是渲染性能。但是,它还不够深入。如果有人向我解释这一点或为我指出一些易于消化的材料,然后再开始进行规范研究,我将不胜感激。
预先感谢

I'm pretty sure it is due to the fact that CSS animation is being handled outside of javascript event loop, but I'm not sure if my assumption is correct. The closest article that explains internals is this - Rendering Performance. However, it does not go deep enough. I will appreciate if someone explains this or points me to some digestible material to read/watch before I go hardcore and start looking for specs. Thanks in advance

这是因为规范鼓励实施者不遵循规范...

This is because implementers are encouraged by the specs to not follow the specs...

alert()调用暂停算法,该算法应该阻止当前任务,并导致事件循环除了等待条件目标得到满足。

alert() calls the pause algorithm, which should block the current task and cause the event loop to have nothing to do anymore than waiting for the "condition goal is met".

尽管如此,该页面上还有一个警告段落,指出:

Though, this page also has a big warning paragraph stating,


暂停是非常不利于用户体验,尤其是在单个事件循环在多个文档之间共享。鼓励用户代理尝试暂停的替代方法,例如旋转事件循环,甚至直接进行而无需在可能的情况下,在保持与现有内容的兼容性的范围内,可以进行任何类型的暂停执行。如果发现不太苛刻的替代方法与Web兼容,则此规范将很高兴地更改。

Pausing is highly detrimental to the user experience, especially in scenarios where a single event loop is shared among multiple documents. User agents are encouraged to experiment with alternatives to pausing, such as spinning the event loop or even simply proceeding without any kind of suspended execution at all, insofar as it is possible to do so while preserving compatibility with existing content. This specification will happily change if a less-drastic alternative is discovered to be web-compatible.

因此,您的UA当然会遵循建议试用 旋转事件-循环 替代方案,即使调用 alert()的任务已被暂停,它也允许其他任务继续运行。

So your UA certainly followed the advice to experiment with a spin-the-event-loop alternative, which allows for other tasks to still run, even though the one that called alert() has been paused.