获取动画信息
想象其他方式我们可以使用 playbackRate,例如通过让他们减慢整个网站的动画来改善具有前庭障碍的用户的无障碍。这不可能在 CSS 中重新计算每个 CSS 规则的持续时间,但是通过 Web 动画 API,我们可以使用即将到来的(在浏览器中不支持!)document.getAnimations()方法 循环遍历页面上的每个动画,并将它们的播放速度减半:
jsdocument.getAnimations().forEach(function (animation) {
animation.playbackRate *= 0.5;
});
使用 Web 动画 API,你需要更改的只是一个小的属性!
另一件与 CSS 动画有关的难点就是创建依赖于其他动画提供的值。例如,在“成长和收缩爱丽丝”游戏的例子中,你可能会注意到蛋糕的持续时间有些奇怪:
jsdocument.getElementById("eat-me_sprite").animate([], {
duration: aliceChange.effect.timing.duration / 2,
});
要了解这里发生了什么,让我们来看看 Alice 的动画:
jsconst aliceChange = document
.getElementById("alice")
.animate(
[
{ transform: "translate(-50%, -50%) scale(.5)" },
{ transform: "translate(-50%, -50%) scale(2)" },
],
{
duration: 8000,
easing: "ease-in-out",
fill: "both",
},
);
爱丽丝的动画让她的尺寸在 8 秒内从一半到两倍。然后我们暂停她:
jsaliceChange.pause();
如果我们在动画开始时已经把她暂停了,那么她的全部尺寸将从一半开始,就像她已经把整个瓶子都喝完了一样!我们想把动画的“播放头”放在中间,这样她就在半途了。我们可以通过将她的 Animation.currentTime 设置为 4 秒,如下所示:
jsaliceChange.currentTime = 4000;
但是在制作这个动画的时候,我们可能会改变爱丽丝的持续时间。如果我们将她的 currentTime 设置为动态的,它不会更好吗?所以我们不必一次做两个更新?我们实际上可以通过引用 aliceChange 的 Animation.effect 属性来实现,该属性返回一个包含 Alice 上所有效果细节的对象:
jsaliceChange.currentTime = aliceChange.effect.timing.duration / 2;
effect 让我们能够访问动画的关键帧和时间对象——aliceChange.effect.timing 指向 Alice 的时间对象(其类型为 AnimationEffectTimingReadOnly)——这包含她的 AnimationEffectTimingReadOnly.duration。我们可以将她的持续时间分成两半,以获得她动画时间轴的中点,使她成为正常的高度。现在,我们可以在任何一个方向扭转和播放动画,使她变小或变大!
当设置蛋糕和瓶子的持续时间时,我们可以做同样的事情:
jsconst drinking = document
.getElementById("liquid")
.animate([{ height: "100%" }, { height: "0" }], {
fill: "forwards",
duration: aliceChange.effect.getComputedTiming().duration / 2,
});
drinking.pause();
现在,所有三个动画只有一个持续时间,我们可以从一个地方容易地改变。
我们还可以使用 Web 动画 API 来确定动画当前的时间。当你用尽蛋糕吃或者清空瓶子时,游戏就结束了。哪个角色扮演者取决于爱丽丝在她的动画中有多远,无论她是否变得太大,不能进入小门太小,无法达到打开门的钥匙。我们可以弄清楚她是否在动画的大端或小端,让她的动画当前时间 (currentTime) 被她的 activeDuration 分成:
jsconst endGame = () => {
// get Alice's timeline's playhead location
const alicePlayhead = aliceChange.currentTime;
const aliceTimeline = aliceChange.effect.getComputedTiming().activeDuration;
// stops Alice's and other animations
stopPlayingAlice();
// depending on which third it falls into
const aliceHeight = alicePlayhead / aliceTimeline;
if (aliceHeight <= 0.333) {
// Alice got smaller!
// …
} else if (aliceHeight >= 0.666) {
// Alice got bigger!
// …
} else {
// Alice didn't change significantly
// …
}
};
备注:getAnimations() and effect are not fully supported as of this writing, but the polyfill does support them today.