美文网首页
async/await在CSS动画控制中的简单应用

async/await在CSS动画控制中的简单应用

作者: DaveJump | 来源:发表于2017-07-25 11:49 被阅读0次

    最近在做一个H5动画的小项目,由于项目周期充裕,前期主要是搭架构,也没用其他多余的动画库。由于经验不足,在搭架构的过程中也遇到挺多坑,比如webpack的配置问题、场景动画类的封装等等。这次就记录下如何异步控制动画的出现和消失。

    回顾ES6的Promise和ES7的async/await

    在ES6出来之前和不用其他动画库的情况下,很多人做简单动画基本都是用css3 animation + setTimeout + jQuery animate,但这样却面临一个问题:没错,回调地狱和嵌套层次太深,代码可读性大打折扣。
    但现在有了ES6、ES7和babel,我们可以大胆地用promise和async/await来做动画的异步执行。
    async函数是generator的一个语法糖,目前能被babel编译。它的优点在于外部不需要手动调用next方法,也不需要链式调用then方法,可以说是优于promise和generator。用法非常简单,来看一个简单例子:

    const getUserData = url => (
        new Promise((resolve, reject) => {
           axios.get(url)
             .then(({ data }) => resolve(data))
             .catch(error => reject(error));
        })
    );
    const getUserDataByAsync = async () => {
        let _username;
        try{
          const { username } = await getUserData('https://github.com/username');
          _username = username;
          if(_username) {
            /* do something */
          }
        }catch(err){
          console.log(err);
        }
    };
    getUserDataByAsync();
    
    • 首先我们定义了一个getUserData函数,返回一个promise对象实例,用于抓取github上的用户信息。axios的get方法返回的也是一个promise对象,请求成功后会执行第一层promise的resolve方法,并把请求到的数据传出去。
    • 接下来定义一个名为getUserDataByAsync的async函数(也可以这么声明: async function getUserDataByAsync(){}),用于处理请求成功后的操作。await关键字后调用getUserData,而在此之后的代码(在try之内,await之后)则会被阻塞,待请求成功后才会继续执行。await getUserData()的返回值则是getUserData函数里resolve后传入的data。这里我们用try-catch来捕获请求失败后的异常信息,catch打印出来的则是getUserData里请求失败后reject传入的error。
    • 最后再调用getUserDataByAsync函数就行了。
    我们用同样的方法封装一个动画延时器
    • 首先我们先封装动画方法,这里为了操作节点方便一点用了jQuery
    const animate = several => {
         for (let effectName in several) {
           let effect = `${effectName}`,
               element_list = (several[effectName] instanceof Array) ? several[effectName] : [];
    
           element_list.forEach(element => {
             //为了防止display和animation冲突我们需要判断元素是否被隐藏了
             if ($(element).is(':hidden')) {
               $(element).show();
               setTimeout(() => {
                 $(element).addClass(`animated ${effect}`);
               }, 10);
             } else {
               $(element).addClass(`animated ${effect}`);
             }
           });
         }
    };
    

    需配合自己写的css3 animation或引入animate.css库。

    • 再封装一个延时器
    const delay = (timeout = 0) => (
        new Promise(resolve => {
          setTimeout(resolve, timeout);
        })
    );
    
    • 之后就可以随意控制动画的出现和消失了
    const pageAnimationStart = async () => {
        const _sceneWrap= $('#scene-wrap'),
              _title = _scene_wrap.find('.title'),
              _tree =  _scene_wrap.find('.tree'),
              _apples = _scene_wrap.find('.apple');
    
        animate({
          'scaleIn': [_sceneWrap]
        });
    
        await delay(1000);
    
        animate({
          'slideBounceInDown': [_tree]
        });
    
        await delay(1500);
    
        animate({
          'bounceIn': [_title, _apples]
        });
    };
    window.addEventListener('load', function(){
        pageAnimationStart();
    }, false);
    

    页面加载完成后,场景开始,先是整个场景背景_sceneWrap放大进入,1秒后大树_tree由上到下掉入,再过1.5秒后标题_title和苹果_apples跳入。
    大概就是这样一个步奏,以异步执行、同步写法的方式,看起来特别舒服,清晰地展示了每一步该做什么,避免了的嵌套、回调和满屏的then方法。

    这就是async/await在动画处理中的简单方法。其他应用场景等我研究过后再记录吧!

    相关文章

      网友评论

          本文标题:async/await在CSS动画控制中的简单应用

          本文链接:https://www.haomeiwen.com/subject/nfxwkxtx.html