美文网首页
动画3——钩子函数实现半场动画

动画3——钩子函数实现半场动画

作者: 小丘啦啦啦 | 来源:发表于2019-04-19 09:40 被阅读0次

    一、说明
    前两种都是一个完整动画,也无法实现半场动画。
    需要实现半场动画,只需要入场动画。
    可以在属性中声明JavaScript 钩子,即v-on绑定事件指向methods中函数,按需要声明。

    <transition
      v-on:before-enter="beforeEnter"
      v-on:enter="enter"
      v-on:after-enter="afterEnter"
      v-on:enter-cancelled="enterCancelled"
    
      v-on:before-leave="beforeLeave"
      v-on:leave="leave"
      v-on:after-leave="afterLeave"
      v-on:leave-cancelled="leaveCancelled"
    >
    </transition>
    

    写各个自己需要的动画的生命周期函数,可以只要入场或只要出场。

    // ...
    methods: {
      // --------
      // 进入中
      // --------
      //动画入场之前
      beforeEnter: function (el) {
        // ...
      },
      // 当与 CSS 结合使用时
      // 回调函数 done 是可选的
      //动画效果(最终位置、中间过渡)
      enter: function (el, done) {
        // ...
        done()
      },
      //动画完成之后会调用
      afterEnter: function (el) {
        // ...
      },
      enterCancelled: function (el) {
        // ...
      },
    
      // --------
      // 离开时
      // --------
    
      beforeLeave: function (el) {
        // ...
      },
      // 当与 CSS 结合使用时
      // 回调函数 done 是可选的
      leave: function (el, done) {
        // ...
        done()
      },
      afterLeave: function (el) {
        // ...
      },
      // leaveCancelled 只用于 v-show 中
      leaveCancelled: function (el) {
        // ...
      }
    }
    

    动画钩子函数的第一个参数el表示要执行动画的那个DOM元素,原生JS DOM对象。

    • 当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。
    • done()其实就是afterEnterafterLeave的引用。

    二、实例
    点击按钮后出现红点掉落消失的半场效果。

    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
            <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
            <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
            <style>
                .ball{
                    width: 15px;
                    height: 15px;
                    background-color: red;
                    border-radius: 50%;
                }
            </style>
        </head>
        <body>
            <div id="app">
                <input type="button" value="加入购物车" @click="flag = !flag" />
                <transition v-on:before-enter="beforeEnter"
                            v-on:enter="enter"
                            v-on:after-enter="afterEnter">
                    <div class="ball" v-show="flag"></div>
                </transition>
            </div>
            <script>
                var vm = new Vue({
                    el: "#app",
                    data: {
                        flag: false
                    },
                    methods:{
                        beforeEnter(el){   //动画入场前,设置小球的起始位置
                            el.style.transform = "translate(0,0)";
                        },
                        enter(el,done){   //动画效果
                            //TODO 这里没有实际作用,但是不调用,没有动画效果?
                            //认为这个会强制刷新动画效果
                            el.offsetWidth;   //offsetHeight...等
                            el.style.transform = "translate(150px,450px)";
                            el.style.transition = "all 1s ease";
                            done();   //动画完成之后会立即执行消失,其实就是afterEnter函数的引用
                        },
                        afterEnter(el){   //动画结束后
                            this.flag = !this.flag;   //隐藏了小球,但是小球位置还是在结束位置
                            //下次点击会执行下次动画的生命周期,即beforeEnter开始,又会回到起始位置
                        }
                    }
                });
            </script>
        </body>
    </html>
    
    • enter钩子函数中一定要调用一下el.offsetWidth;,不然不会有动画中间效果,只有开始和结束状态。
    • 虽然动画结束后只让小球消失了而没有初始化小球位置,这不影响。下次点击会执行新的动画生命周期,即会执行beforeEnter重新初始化了小球位置。

    三、修改flag标识的作用
    上面实例中,我们使用flag属性作为标识符,来表示动画的切换。
    Vue把一个完整的动画,使用钩子函数,拆分成了两部分,flag值的改变表示了上半场动画和下半场动画。
    前半场刚开始,flag = false -> true;后半场结束时应该flag = true -> false,但此处没有后半场动画(只是半场动画),则在afterEnter中执行,控制小球隐藏,并且直接跳过后半场动画。

    • 所以说,如果最后没有改变flagfalse让元素消失(例如直接在afterEnter中改变元素opacity),下次再点进行取非就是flag=ture->false,已经不是前半场动画的逻辑了,这样做是不行的后面就不生效了。
      错误:
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
            <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
            <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
            <style>
                .ball{
                    width: 15px;
                    height: 15px;
                    background-color: red;
                    border-radius: 50%;
                }
            </style>
        </head>
        <body>
            <div id="app">
                <input type="button" value="加入购物车" @click="flag = !flag" />
                <transition v-on:before-enter="beforeEnter"
                            v-on:enter="enter"
                            v-on:after-enter="afterEnter">
                    <div class="ball" v-show="flag"></div>
                </transition>
            </div>
            <script>
                var vm = new Vue({
                    el: "#app",
                    data: {
                        flag: false
                    },
                    methods:{
                        beforeEnter(el){   //此时flag=false
                            el.style.transform = "translate(0,0)";
                        },
                        enter(el,done){   //此时flag取非=true
                            el.offsetWidth; 
                            el.style.transform = "translate(150px,450px)";
                            el.style.transition = "all 1s ease";
                            done();  
                        },
                        afterEnter(el){   //动画结束后
                            el.style.opacity=0;   //没有让flag=false让动画结束,而是直接改变了opacity,下次动画入场过程就错误了
                        }
                    }
                });
            </script>
        </body>
    </html>
    

    相关文章

      网友评论

          本文标题:动画3——钩子函数实现半场动画

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