问题
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">♥</div> CSS</div>
<div class="heart">I
<div class="animate-js heart">♥</div> JS</div>
<br/>
<button onClick="alert('hurray!')">
I love it too
</button>
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
回答1:
This is because implementers are encouraged by the specs to not follow the specs...
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,
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.
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.
回答2:
Yes, from what I am reading, CSS animation appear to be outside the Javascript event loop. But, while they are running concurrently, you can control the animations with Javascript calls.
Here is a collection of reading material: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations
In particular, animation-play-state is the property I think you're after. Setting it to paused right before you call the Javascript alert would be how I'd approach it. Once the user clicks the appropriate button in the alert, set the property back to running to resume the animation.
来源:https://stackoverflow.com/questions/52325435/why-blocking-event-loop-does-not-block-css-animation