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

2019-04-19  本文已影响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对象。

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

<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>

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

<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>
上一篇下一篇

猜你喜欢

热点阅读