大家好,我是你们今天的动画魔法师!今天咱们来聊聊前端动画的三剑客:CSS Animations、CSS Transitions,以及它们背后的强大盟友——Web Animations API (WAAPI)。
开场白:动画世界的恩怨情仇
想象一下,CSS Animations 和 Transitions 就像一对老搭档,它们默契十足,用 CSS 就能轻松搞定页面上的各种小动画。但是,它们也有自己的局限性,比如想要精确控制动画的每一个细节,或者让动画和 JavaScript 代码互动,就有点力不从心了。这时候,WAAPI 就闪亮登场了!它就像一位超级英雄,赋予了我们用 JavaScript 直接操控动画的能力,让动画的世界变得更加灵活和可控。
第一幕:CSS Animations 与 Transitions 的爱恨情仇
先来回顾一下 CSS Animations 和 Transitions 的基本用法,毕竟它们是 WAAPI 的基石。
-
CSS Transitions: 适用于状态变化之间的平滑过渡。
.box { width: 100px; height: 100px; background-color: red; transition: width 0.5s ease-in-out, background-color 0.3s linear; } .box:hover { width: 200px; background-color: blue; }
这段代码的意思是,当鼠标悬停在
.box
元素上时,它的宽度会在 0.5 秒内平滑地过渡到 200px,颜色会在 0.3 秒内线性地过渡到蓝色。 -
CSS Animations: 适用于更复杂的、具有多个关键帧的动画序列。
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .spinner { width: 50px; height: 50px; border-radius: 50%; border: 3px solid black; animation: spin 2s linear infinite; }
这段代码定义了一个名为
spin
的关键帧动画,它会让元素旋转 360 度。然后,我们将这个动画应用到.spinner
元素上,让它以 2 秒的周期线性地无限旋转。
第二幕:WAAPI 的英雄登场
WAAPI 允许我们使用 JavaScript 来创建、控制和操作动画。它的核心是 Element.animate()
方法。
const element = document.querySelector('.box');
const animation = element.animate(
[
{ transform: 'translateX(0)' },
{ transform: 'translateX(100px)' }
],
{
duration: 1000,
iterations: Infinity,
direction: 'alternate'
}
);
这段代码创建了一个动画,让 .box
元素在水平方向上从 0px 平移到 100px,动画持续 1 秒,无限循环,并且来回交替播放。
第三幕:WAAPI 与 CSS Animations/Transitions 的互操作性
重点来了!WAAPI 并不是要取代 CSS Animations 和 Transitions,而是要和它们协同工作,取长补短。
-
读取 CSS 动画和过渡的属性: WAAPI 允许我们读取 CSS 动画和过渡的属性,例如
duration
、delay
、easing
等。这使得我们可以基于现有的 CSS 动画来创建更复杂的动画效果。const element = document.querySelector('.box'); element.style.transition = 'width 0.5s ease-in-out'; // 设置CSS过渡 element.style.width = '200px'; // 触发过渡 // 等待过渡结束后,读取过渡属性 setTimeout(() => { const transitionDuration = parseFloat(getComputedStyle(element).transitionDuration) * 1000; console.log("Transition duration from CSS:", transitionDuration); // 输出:500 }, 600);
-
控制 CSS 动画和过渡的播放: WAAPI 允许我们暂停、恢复、反转 CSS 动画和过渡的播放。
const element = document.querySelector('.spinner'); element.style.animation = 'spin 2s linear infinite'; // 应用CSS动画 // 暂停动画 element.style.animationPlayState = 'paused'; // 恢复动画 element.style.animationPlayState = 'running';
-
将 WAAPI 动画应用到 CSS 类: 我们可以使用 JavaScript 创建 WAAPI 动画,然后将它们应用到 CSS 类上,从而实现更灵活的动画控制。
// 创建 WAAPI 动画 const animation = element.animate( [ { transform: 'rotate(0deg)' }, { transform: 'rotate(360deg)' } ], { duration: 2000, iterations: Infinity, easing: 'linear' } ); // 将动画应用到 CSS 类 element.classList.add('rotating'); // 停止动画,移除 CSS 类 animation.cancel(); element.classList.remove('rotating');
这段代码的关键在于,我们需要自己控制动画的生命周期,并在适当的时候取消动画,并移除相关的 CSS 类。
第四幕:WAAPI 的性能优势
WAAPI 的一个重要优势是它的性能。WAAPI 动画是由浏览器直接处理的,这意味着它们可以充分利用硬件加速,从而提供更流畅、更高效的动画体验。
- 硬件加速: WAAPI 动画通常比使用 JavaScript 定时器或
requestAnimationFrame
实现的动画更流畅,因为它们可以利用 GPU 进行硬件加速。 - 减少 JavaScript 负担: WAAPI 将动画的计算和渲染工作交给浏览器处理,从而减轻了 JavaScript 的负担,提高了页面的整体性能。
第五幕:WAAPI 的时间线控制
WAAPI 提供了强大的时间线控制功能,允许我们精确地控制动画的播放。
-
currentTime
属性: 可以设置或获取动画的当前时间。const animation = element.animate( [ { transform: 'translateX(0)' }, { transform: 'translateX(100px)' } ], { duration: 1000 } ); // 将动画跳转到 500 毫秒的位置 animation.currentTime = 500; // 获取动画的当前时间 const currentTime = animation.currentTime; console.log(currentTime); // 输出:500
-
playbackRate
属性: 可以设置动画的播放速度。const animation = element.animate( [ { transform: 'translateX(0)' }, { transform: 'translateX(100px)' } ], { duration: 1000 } ); // 将动画的播放速度设置为 2 倍 animation.playbackRate = 2; // 将动画的播放速度设置为 -1 倍(反向播放) animation.playbackRate = -1;
-
play()
、pause()
、reverse()
方法: 可以控制动画的播放状态。const animation = element.animate( [ { transform: 'translateX(0)' }, { transform: 'translateX(100px)' } ], { duration: 1000 } ); // 暂停动画 animation.pause(); // 播放动画 animation.play(); // 反向播放动画 animation.reverse();
-
finish()
方法: 立即完成动画。const animation = element.animate( [ { transform: 'translateX(0)' }, { transform: 'translateX(100px)' } ], { duration: 1000 } ); // 立即完成动画 animation.finish();
-
cancel()
方法: 取消动画,并将其恢复到初始状态。const animation = element.animate( [ { transform: 'translateX(0)' }, { transform: 'translateX(100px)' } ], { duration: 1000 } ); // 取消动画 animation.cancel();
第六幕:WAAPI 的事件监听
WAAPI 提供了 onfinish
和 oncancel
事件,允许我们监听动画的完成和取消事件。
const animation = element.animate(
[
{ transform: 'translateX(0)' },
{ transform: 'translateX(100px)' }
],
{
duration: 1000
}
);
animation.onfinish = () => {
console.log('Animation finished!');
};
animation.oncancel = () => {
console.log('Animation cancelled!');
};
第七幕:WAAPI 的高级用法:AnimationTimeline
AnimationTimeline
接口允许我们创建和管理多个动画的时间线。它提供了一种更高级的方式来控制动画的播放和同步。虽然 AnimationTimeline
尚未得到所有浏览器的完全支持,但它代表了 WAAPI 的未来方向。
// 创建一个时间线
const timeline = document.timeline;
// 创建两个动画
const animation1 = element1.animate(
[
{ transform: 'translateX(0)' },
{ transform: 'translateX(100px)' }
],
{
duration: 1000,
timeline: timeline // 将动画添加到时间线
}
);
const animation2 = element2.animate(
[
{ transform: 'rotate(0deg)' },
{ transform: 'rotate(360deg)' }
],
{
duration: 2000,
timeline: timeline // 将动画添加到时间线
}
);
// 调整时间线的时间,可以控制所有动画的播放
timeline.currentTime = 500;
第八幕:实战演练:一个复杂的动画场景
假设我们需要创建一个页面,其中包含一个按钮,点击按钮后,一个元素会从左侧滑入,然后旋转 360 度,最后淡出。
<button id="animateButton">Animate</button>
<div id="animatedElement">Hello, Animation!</div>
#animatedElement {
position: absolute;
left: -200px; /* 初始位置在屏幕外 */
opacity: 0;
width: 200px;
height: 100px;
background-color: lightblue;
text-align: center;
line-height: 100px;
}
const animateButton = document.getElementById('animateButton');
const animatedElement = document.getElementById('animatedElement');
animateButton.addEventListener('click', () => {
// 创建动画序列
const slideIn = animatedElement.animate(
[
{ transform: 'translateX(-200px)', opacity: 0 },
{ transform: 'translateX(0)', opacity: 1 }
],
{
duration: 500,
easing: 'ease-out'
}
);
slideIn.onfinish = () => {
const rotate = animatedElement.animate(
[
{ transform: 'rotate(0deg)' },
{ transform: 'rotate(360deg)' }
],
{
duration: 1000,
easing: 'linear'
}
);
rotate.onfinish = () => {
const fadeOut = animatedElement.animate(
[
{ opacity: 1 },
{ opacity: 0 }
],
{
duration: 500,
easing: 'ease-in'
}
);
fadeOut.onfinish = () => {
// 动画完成后,将元素重置到初始状态
animatedElement.style.transform = 'translateX(-200px)';
animatedElement.style.opacity = '0';
};
};
};
});
在这个例子中,我们使用了 WAAPI 的 onfinish
事件来串联多个动画,从而实现了一个复杂的动画序列。
第九幕:WAAPI 的浏览器兼容性
虽然 WAAPI 已经得到了主流浏览器的广泛支持,但在一些旧版本的浏览器中可能需要使用 polyfill。你可以使用 web-animations-js 这个 polyfill 来提供 WAAPI 的支持。
第十幕:总结与展望
我们来总结一下 WAAPI 的优势:
- 强大的控制能力: 允许我们使用 JavaScript 精确地控制动画的时间线和播放。
- 高性能: 可以利用硬件加速,提供更流畅、更高效的动画体验。
- 灵活的互操作性: 可以与 CSS Animations 和 Transitions 协同工作,取长补短。
- 事件监听: 提供了
onfinish
和oncancel
事件,方便我们监听动画的完成和取消事件。
WAAPI 代表了前端动画的未来方向。随着浏览器的不断发展,WAAPI 的功能将会越来越强大,应用场景也会越来越广泛。掌握 WAAPI,将使你成为一名真正的动画大师!
结束语:动画的无限可能
希望今天的讲座能让你对 WAAPI 有更深入的了解。动画的世界充满了无限可能,让我们一起用 WAAPI 创造出更精彩、更生动的用户体验吧!祝大家编码愉快!