为什么CSS动画和过渡会被JavaScript阻塞
当JavaScript用于修改动画和过渡所基于的CSS属性时,JavaScript可能会阻止CSS动画和过渡。如果在动画或过渡完成之前修改了属性,动画或过渡可能会突然停止或完全不显示。这是因为JavaScript改变页面的速度过快,使浏览器的渲染器无法跟上。这可能导致糟糕的用户体验,使网站看起来破碎或无响应。问题在于浏览器无法应对JavaScript所做的调整,并且无法跟上页面上正在进行的动画或过渡。
可以通过使用回调或承诺来解决此问题,以等待浏览器完成动画或过渡后再进行任何更改,而且只在必要时才进行。
解除CSS动画和过渡的方法:
谨慎使用JavaScript: 只在绝对必要时使用JavaScript,并避免使用它对正在进行动画或过渡的CSS属性进行更改。
示例: 此示例展示了上述解决方法的应用。
HTML
<body style="text-align:center">
<h1 style="color: green">
Geeksforgeeks
</h1>
<h3>
Unblocking Blocked CSS Animations and Transitions
</h3>
<p class="my-element">
Using Javascript Sparingly
</p>
<style>
.my-element {
position: absolute;
animation: move-left 1s;
}
@keyframes move-left {
from { left: 0; }
to { left: 100px; }
}
</style>
<script>
document.querySelector(".my-element").addEventListener
("click", function() {
// Only use JavaScript when it is absolutely necessary
this.style.top = "100px";
});
</script>
</body>
输出: 动画将连续平稳地进行,不会中断。
使用回调或者Promise: 使用回调或者Promise来确保浏览器在使用JavaScript进行任何更改之前已经完成了动画或者转换。这将防止动画或者转换被中断。
例子: 这个例子展示了上述解释方法的使用。
HTML
<body style="text-align:center">
<h1 style="color: green">
Geeksforgeeks
</h1>
<h3>
Unblocking Blocked CSS Animations and Transitions
</h3>
<p class="my-element">
Using callbacks or promises
</p>
<style>
.my-element {
position: absolute;
animation: move-left 1s;
}
@keyframes move-left {
from { left: 0; }
to { left: 100px; }
}
</style>
<script>
document.querySelector(".my-element").addEventListener("click", function() {
// Use a callback to ensure the animation is finished before making changes
this.animate(
{ top: "100px" },
{
duration: 1000,
complete: function() {
// make changes here
}
}
);
});
</script>
</body>
输出: 动画将在更改之前完成,从而实现平滑过渡。
使用“animation-play-state”属性: 此属性可用于暂停和恢复动画,允许您控制动画何时播放和暂停。
示例: 该示例演示了上述方法的使用。
HTML
<body style="text-align:center">
<h1 style="color: green">
Geeksforgeeks
</h1>
<h3>
Unblocking Blocked CSS Animations and Transitions
</h3>
<p class="my-element">
Using the 'animation-play-state' property
</p>
<style>
.my-element {
position: absolute;
animation: move-left 1s;
animation-play-state: paused;
}
@keyframes move-left {
from { left: 0; }
to { left: 100px; }
}
</style>
<script>
document.querySelector(".my-element").addEventListener("click", function() {
// Use the animation-play-state property to pause and resume the animation
this.style.animationPlayState = "running";
});
</script>
</body>
输出: 默认情况下,动画将被暂停,并且可以通过将“animation-play-state”属性的值更改为“running”来恢复播放。
使用 ‘requestAnimationFrame()’ 方法: 此方法可以用于同步JavaScript和浏览器渲染,使您能够以不干扰动画或过渡的方式对页面进行更改。
示例: 此示例展示了上述解释的方法的使用。
HTML
<body style="text-align:center">
<h1 style="color: green">
Geeksforgeeks
</h1>
<h3>
Unblocking Blocked CSS Animations and Transitions
</h3>
<p class="my-element">
Using the 'requestAnimationFrame()' method
</p>
<style>
.my-element {
position: absolute;
animation: move-left 1s;
}
@keyframes move-left {
from { left: 0; }
to { left: 100px; }
}
</style>
<script>
function updatePosition() {
document.querySelector(".my-element").style.top = "100px";
requestAnimationFrame(updatePosition);
}
requestAnimationFrame(updatePosition);
</script>
</body>
输出: 元素的位置将会平滑地更新,并与浏览器的渲染保持同步。
使用状态管理库: 一些像React、Vue或Angular之类的JavaScript库已经提供了一种管理组件状态的方式,通过这样做可以避免不必要的重新渲染和DOM操作,从而避免动画和过渡被阻塞的问题。
示例: 这个示例展示了上述解释的使用方法。
HTML
<body style="text-align:center">
<h1 style="color: green">
Geeksforgeeks
</h1>
<h3>
Unblocking Blocked CSS Animations and Transitions
</h3>
<p class="my-element">
Using a state management library
</p>
<div id="root"></div>
<style>
.my-element {
position: absolute;
animation: move-left 1s;
}
@keyframes move-left {
from { left: 0; }
to { left: 100px; }
}
</style>
<script>
import React from 'react';
import { render } from 'react-dom';
const MyComponent = () => {
const [position, setPosition] = React.useState({left:0,top:0});
return (
<div
className="my-element"
style={{ left: position.left, top:position.top}}
onClick={() => setPosition({left:position.left+100,top:position.top+100})}
>
Click me
</div>
)
}
render(<MyComponent />, document.getElementById('root'));
</script>
</body>
输出: 当必要时,组件将重新渲染,并且通过这样做,它不会中断动画。
使用CSS-in-JS库: 这些库允许您使用JavaScript定义和控制CSS样式,但它们在内部处理DOM的渲染和操作,并可以帮助保持动画和过渡的流畅性。
例子: 此示例展示了上述解释的方法的使用。
HTML
<body style="text-align:center">
<h1 style="color: green">
Geeksforgeeks
</h1>
<h3>
Unblocking Blocked CSS Animations and Transitions
</h3>
<p class="my-element">
Using CSS-in-JS libraries:
</p>
<div id="root"></div>
<style>
.my-element {
position: absolute;
animation: move-left 1s;
}
@keyframes move-left {
from { left: 0; }
to { left: 100px; }
}
</style>
<script>
import React from 'react';
import { render } from 'react-dom';
import { css, keyframes } from '@emotion/core'
const moveLeft = keyframes`
from { left: 0 }
to { left: 100px }
`
const myElement = css`
animation: ${moveLeft} 1s;
position: absolute;
`
const MyComponent = () => <div className={myElement}>Example</div>
render(<MyComponent />, document.getElementById('root'));
</script>
</body>
输出: 样式是在JavaScript中定义的,库将处理DOM操作。
参考: https://developer.mozilla.org/en-US/docs/Web/Performance/CSS_JavaScript_animation_performance