使用 Promise 编排动画、可替换动画带来的性能改进、复合模式带来的更流畅动画等等。
发布时间:2020 年 5 月 27 日
如果使用得当,动画可以提升用户对您品牌的感知和记忆,引导用户操作,并帮助用户浏览您的应用程序,从而在数字空间中提供上下文。
Web Animations API 是一种工具,使开发者能够使用 JavaScript 编写命令式动画。它的编写目的是为了支持 CSS 动画和过渡效果的实现,并支持未来效果的开发,以及现有效果的组合和定时。
虽然 Firefox 和 Safari 已经实现了完整的规范 功能集,但 Chromium 84 为 Chrome 和 Edge 带来了一系列以前不受支持的功能,从而实现了跨浏览器互操作性。

入门指南
如果您使用过 @keyframe
规则,那么使用 Web Animations API 创建动画应该会感到非常熟悉。首先,您需要创建一个关键帧对象。在 CSS 中,它可能看起来像这样
@keyframes openAnimation {
0% {
transform: scale(0);
}
100% {
transform: scale(1);
}
}
在 JavaScript 中,它看起来会像这样
const openAnimation = [
{ transform: 'scale(0)' },
{ transform: 'scale(1)' },
];
在 CSS 中设置动画参数的位置
.modal {
animation: openAnimation 1s 1 ease-in;
}
您可以在 JS 中设置
document.querySelector('.modal').animate(
openAnimation, {
duration: 1000, // 1s
iterations: 1, // single iteration
easing: 'ease-in' // easing function
}
);
代码量大致相同,但使用 JavaScript,您可以获得一些仅使用 CSS 无法获得的超能力。这包括对效果进行排序的能力,以及对它们播放状态的增强控制。
超越 element.animate()
但是,通过更新,Web Animations API 不再局限于使用 element.animate()
创建的动画。我们也可以操作 CSS 动画和过渡效果。
getAnimations()
是一种方法,它可以返回元素上的所有动画,无论它是使用 element.animate()
创建的还是使用 CSS 规则(CSS 动画或过渡效果)创建的。以下是它的示例
首先,您 "get"
过渡的关键帧,以确定我们从哪里开始过渡。然后,您创建两个新的不透明度动画,从而实现交叉淡入淡出效果。交叉淡入淡出完成后,删除副本。
如何使用 Promise 编排动画
在 Chromium 84 中,您现在可以使用两种与 Promise 结合使用的方法:animation.ready
和 animation.finished
。
animation.ready
让您可以等待待处理的更改生效(即,在播放和暂停等播放控制方法之间切换)。animation.finished
提供了一种在动画完成时执行自定义 JavaScript 代码的方法。
继续我们的示例,并使用 animation.finished
创建一个编排好的动画链。在这里,您有一个垂直变换 (scaleY
),然后是一个水平变换 (scaleX
),最后是子元素的不透明度更改
const transformAnimation = modal.animate(openModal, openModalSettings);
transformAnimation.finished.then(() => { text.animate(fadeIn, fadeInSettings)});
我们在链中执行下一个动画集之前,使用 animation.finished.then()
将这些动画链接起来。这样,动画会按顺序显示,您甚至可以将效果应用于具有不同选项集(例如速度和缓动)的不同目标元素。
在 CSS 中,这将很难重新创建,尤其是在将独特但按顺序排列的动画应用于多个元素时。您必须使用 @keyframe
,整理出正确的计时百分比来放置动画,并在序列中触发动画之前使用 animation-delay
。
示例:播放、暂停和反向
可以打开的,就应该可以关闭!幸运的是,自 Chromium 39 以来,Web Animations API 为我们提供了播放、暂停和反转动画的能力。
您可以采用先前显示的动画,并在再次单击按钮时使用 .reverse()
为其提供平滑的反向动画。这样,您可以为我们的模态创建更平滑、更具上下文的交互。
您可以做的是创建两个待播放的动画(openModal
和内联不透明度变换),然后暂停其中一个动画,将其延迟到另一个动画完成后再播放。然后,您可以使用 Promise 等待每个动画完成再播放。最后,您可以检查是否设置了标志,然后反转每个动画。
示例:使用部分关键帧的动态交互
selector.animate([{transform: `translate(${x}px, ${y}px)`}],
{duration: 1000, fill: 'forwards'});
在此示例中,只有一个关键帧,并且没有指定的起始位置。这是使用部分关键帧的示例。鼠标处理程序在这里执行了几项操作:它设置了一个新的结束位置并触发了一个新的动画。新的起始位置是从当前的基础位置推断出来的。
可以在现有过渡效果仍在运行时触发新的过渡效果。这意味着当前过渡效果会被中断,并创建一个新的过渡效果。
可替换动画带来的性能改进
当基于事件(例如 'mousemove'
)创建动画时,每次都会创建一个新的动画,这可能会快速消耗内存并降低性能。为了解决这个问题,Chromium 83 中引入了可替换动画,从而实现了自动清理,其中完成的动画被标记为可替换,并且如果被另一个完成的动画替换,则会自动删除。请考虑以下示例
elem.addEventListener('mousemove', evt => {
rectangle.animate(
{ transform: translate(${evt.clientX}px, ${evt.clientY}px) },
{ duration: 500, fill: 'forwards' }
);
});
每次鼠标移动时,浏览器都会重新计算彗星轨迹中每个球的位置,并创建一个到这个新点的动画。当满足以下条件时,浏览器现在知道删除旧动画(启用替换):
- 动画已完成。
- 在复合排序中,有一个或多个动画也已完成。
- 新动画正在为相同的属性制作动画。
您可以使用 anim.onremove
触发计数器,通过计算每个删除的动画的计数器来准确查看有多少动画被替换。
还有一些其他属性和方法可以进一步控制您的动画
animation.replaceState
提供了一种跟踪动画是处于活动状态、持久状态还是已删除状态的方法。animation.commitStyles()
基于底层样式以及元素上复合顺序中的所有动画来更新元素的样式。animation.persist()
将动画标记为不可替换。
复合模式带来的更流畅动画
借助 Web Animations API,您现在可以设置动画的复合模式,这意味着除了默认的“replace”模式外,它们还可以是累加的或累积的。复合模式允许开发者编写不同的动画,并控制效果的组合方式。现在支持三种复合模式:'replace'
(默认模式)、'add'
和 'accumulate'
。
当您复合动画时,开发者可以编写简短、不同的效果,并看到它们组合在一起。在以下示例中,我们正在将旋转和缩放关键帧应用于每个框,唯一的调整是复合模式,作为选项添加
在默认的 'replace'
复合模式下,最终动画会替换 transform 属性,并最终达到 rotate(360deg) scale(1.4)
。对于 'add'
,复合模式会添加旋转并乘以缩放,从而产生 rotate(720deg) scale(1.96)
的最终状态。'accumulate'
组合变换,从而产生 rotate(720deg) scale(1.8)
。有关这些复合模式的复杂性的更多信息,请查看 Web Animations 规范中的 CompositeOperation 和 CompositeOperationOrAuto 枚举。
看看以下 UI 元素示例
在这里,复合了两个 top
动画。第一个是宏动画,它将下拉菜单移动整个菜单本身的高度,作为从页面顶部滑入的效果,第二个是微动画,当它到达底部时应用一点弹跳效果。使用 'add'
复合模式可以实现更平滑的过渡。
const dropDown = menu.animate(
[
{ top: `${-menuHeight}px`, easing: 'ease-in' },
{ top: 0 }
], { duration: 300, fill: 'forwards' });
dropDown.finished.then(() => {
const bounce = menu.animate(
[
{ top: '0px', easing: 'ease-in' },
{ top: '10px', easing: 'ease-out' },
{ ... }
], { duration: 300, composite: 'add' });
});
Web Animations API 的未来发展方向
这些都是当今浏览器动画功能的令人兴奋的新增功能,并且还有更多新增功能正在开发中。查看以下未来规范,进一步了解接下来的发展方向