为什么与两个动画共享一个 KeyframesEffect 会导致一个动画永远不会结束?

问题描述

在下面的例子中,一个动画将完成,另一个将继续(因为 playState 不等于完成):

const keyframes = new KeyframeEffect(null,[
    { // from
        opacity: 0,},{ // to
        opacity: 1,}
],{duration: 2000,easing: 'ease'})

{
    const anim = new Animation(
        keyframes,document.timeline
    )

    anim.play()

    requestAnimationFrame(function loop() {
      console.log('1',keyframes.getComputedTiming().progress)
      if (anim.playState != 'finished') requestAnimationFrame(loop)
    },100)
}


{
    const anim = new Animation(
        keyframes,document.timeline
    )

    anim.play()

    requestAnimationFrame(function loop() {
      console.log('2',100)
}

为什么一个动画永远不会“完成”?

解决方法

AnimationEffects,其中 KeyframeEffect 是一个子类,不能在 Animations 之间共享。这是因为它们依赖于与其 Animation 相关联的各种状态。

(特别是,他们需要知道它们是否与过渡/CSS 动画相关联才能正确堆叠,并且他们需要知道动画的播放速率以便在其活动间隔结束时产生正确的值。 )

因此,如果您尝试将 AnimationEffectAnimation 关联,它会从它之前关联的任何 Animation 中删除。这在 set the associated effect of an animation 的过程中指定。

顺便说一下,这就是 KeyframeEffect 接口具有 "copy constructor" 以便您可以克隆 KeyframeEffect 的原因。

因此,在您的示例中,您可以使用以下方法解决此问题:

const anim = new Animation(
  new KeyframeEffect(keyframes),document.timeline
)

现在,至于为什么其中一个动画从未完成,这似乎是 Chrome 中的一个错误。在 Firefox 中,第一个动画(失去了它的 AnimationEffect)将在开始后几乎立即终止,因为它的 associated effect end 变为零。