如何使用Promise链接CSS动画? [英] How to chain CSS animations using Promise?

查看:137
本文介绍了如何使用Promise链接CSS动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试弄清 Promise 的工作原理,并使一个CSS动画在另一个动画中运行。但是它们同时运行...

I'm trying to figure out how Promise works and to make one CSS animation to run after another. But they run simultaneously...

JS小提琴

let move_boxes = () => {
    return new Promise( (resolve, reject) => {
        resolve ('boxes moved!')
    })
};
let move_box_one = () => {
    return new Promise( (resolve, reject) => {
        resolve (document.getElementById('div_two').style.animation = 'move 3s forwards')
        console.log('box one moved!')   
    })

}
let move_box_two = () => {
    return new Promise( (resolve, reject) => {
        resolve (document.getElementById('div_one').style.animation = 'move 3s forwards')
        console.log('box two moved!')       
    })
}

move_boxes().then(() => {
    return move_box_one();
}).then(() => {
    return move_box_two();
});


推荐答案

与发布的答案相反,我不鼓励使用 window.setTimeout ,因为它不能保证计时器与动画结束事件同步,动画结束事件有时会分流到GPU。如果您想更加确定,您应该在听 animationend 事件 ,并在回调本身中对其进行解析,即:

In contrary to the answers posted, I would discourage using window.setTimeout, because it does not guarantee that the timers are in sync with the animation end events, which sometimes are offloaded to the GPU. If you want to be extra sure, you should be listening to the animationend event, and resolving it in the callback itself, i.e.:

let move_box_one = () => {
  return new Promise((resolve, reject) => {
    const el = document.getElementById('div_one');
    const onAnimationEndCb = () => {
      el.removeEventListener('animationend', onAnimationEndCb);
      resolve();
    }

    el.addEventListener('animationend', onAnimationEndCb)
    el.style.animation = 'move 3s forwards';
  });
}

更好的是,因为您正在为两个框编写某种重复的逻辑,您可以将所有内容抽象成一个返回诺言的泛型函数:

Even better, is that since you're writing somewhat duplicated logic for both boxes, you can abstract all that into a generic function that returns a promise:

// We can declare a generic helper method for one-time animationend listening
let onceAnimationEnd = (el, animation) => {
  return new Promise(resolve => {
    const onAnimationEndCb = () => {
      el.removeEventListener('animationend', onAnimationEndCb);
      resolve();
    }
    el.addEventListener('animationend', onAnimationEndCb)
    el.style.animation = animation;
  });
}

let move_box_one = async () => {
  const el = document.getElementById('div_one');
  await onceAnimationEnd(el, 'move 3s forwards');
}
let move_box_two = async () => {
  const el = document.getElementById('div_two');
  await onceAnimationEnd(el, 'move 3s forwards');
}

此外,您的 move_boxes 函数有点复杂。如果要异步运行各个移动框的动画,请将其声明为异步方法,然后仅等待各个移动框的函数调用,即:

Also, your move_boxes function is a little convoluted. If you want to run the individual box-moving animations asynchronous, declare it as an async method and simply await individual box moving function calls, i.e.:

let move_boxes = async () => {
  await move_box_one();
  await move_box_two();
}
move_boxes().then(() => console.log('boxes moved'));

请参见概念验证示例(或者您可以从这是我从您最初的版本中分叉的这个JSFiddle ):

See proof-of-concept example (or you can see it from this JSFiddle that I've forked from your original one):

// We can declare a generic helper method for one-time animationend listening
let onceAnimationEnd = (el, animation) => {
  return new Promise(resolve => {
    const onAnimationEndCb = () => {
      el.removeEventListener('animationend', onAnimationEndCb);
      resolve();
    }
    el.addEventListener('animationend', onAnimationEndCb)
    el.style.animation = animation;
  });
}

let move_box_one = async () => {
  const el = document.getElementById('div_one');
  await onceAnimationEnd(el, 'move 3s forwards');
}
let move_box_two = async () => {
  const el = document.getElementById('div_two');
  await onceAnimationEnd(el, 'move 3s forwards');
}

let move_boxes = async () => {
  await move_box_one();
  await move_box_two();
}
move_boxes().then(() => console.log('boxes moved'));

#div_one {
  width: 50px;
  height: 50px;
  border: 10px solid red;
}

#div_two {
  width: 50px;
  height: 50px;
  border: 10px solid blue;
}

@keyframes move {
  100% {
    transform: translateX(300px);
  }
}

@keyframes down {
  100% {
    transform: translateY(300px);
  }
}

<div id="div_one"></div>
<div id="div_two"></div>

这篇关于如何使用Promise链接CSS动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆