徐向博 / Imin.

使用 async 完成一个 CSS 动画队列
作者:Imin 时间:2021-12-20 分类: 前端

项目需求:动画效果按照规定的顺序执行,演示地址

        const first = box => {
            return new Promise(callback => {
                box.style.transform = 'translate(200px, 0) rotate(90deg)';
                setTimeout(() => {
                    callback();
                }, 1000)
            })
        }
        const second = box => {
            return new Promise(callback => {
                box.style.transform = 'translate(200px, 200px) rotate(180deg)';
                setTimeout(() => {
                    callback();
                }, 1000)
            })
        }
        const third = box => {
            return new Promise(callback => {
                box.style.transform = 'translate(0, 200px) rotate(270deg)';
                setTimeout(() => {
                    callback();
                }, 1000)
            })
        }
        const fourth = box => {
            return new Promise(callback => {
                box.style.transform = 'translate(0, 0) rotate(360deg)';
                setTimeout(() => {
                    callback();
                }, 1000)
            })
        }

        const run = async () => {
            let box = document.querySelector('.box');
            await first(box);
            await second(box);
            await third(box);
            await fourth(box);
            box.style.transform = 'rotate(0)';
            running = false;
        };
        let running = false;
        document.querySelector('button').onclick = function(){
            if(!running) run();
            running = true;
        }

原理

在 async 方法中,在 promise 对象前添加 await 关键,会等待 promise 的状态完成后才继续执行。没有 await 关键字的语句,会按照正常的顺序执行。所以上面 run() 方法的执行顺序是:

  • 1. 获取 dom 
  • 2. 执行 first()
  • 3. 等待 first() 完成,执行 second()
  • 4. 等待 second() 完成,执行 third()
  • 5. 等待 third() 完成,执行 fourth()
  • 6. 等待 fourth() 完成,把 dom 旋转角度复位
  • 7. running 赋值为 false


爬坑

发现 transform 的一个坑:当 transform 在页面加载时就执行,首次执行会没有动画效果,需要触发事件才能真正执行,也可放到 setTimeout 中执行。

本文标签: js async css动画