zoukankan      html  css  js  c++  java
  • Vue.js 动画(三)

    1. Vue 中的动画

    Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。
    包括以下工具:

    • 使用过渡类名:使用 transition 元素包裹要设置动画的元素
    • 第三方 CSS 动画库:animate.css
    • 在过渡钩子函数中使用 JavaScript 直接操作 DOM
    • 列表排序过渡:transition-group

    1.1 单元素过渡

    Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡

    • 条件渲染 (使用 v-if)
    • 条件展示 (使用 v-show)
    • 动态组件
    • 组件根节点

    1.1.1 过渡类名

    在进入/离开的过渡中,会有 6 个 class 切换。

    • v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
    • v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
    • v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
    • v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
    • v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
    • v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

    示例:

    h3 元素设置进入退出动画:

    <style>
        /* 自定义两组样式,来控制 transition 内部的元素实现动画 */
        /* v-enter 时间点,元素进入之前的其实状态,此时还未正式进入 */
        /* v-leave-to 时间点,动画离开之后,离开的终止状态,此时,元素动画已结束 */
        .v-enter,
        .v-levae-to {
            opacity: 0;     /*透明度*/
            transform: translateX(150px);       /*元素从 150px 处飘过来,x 轴*/
        }
    
        /* v-enter-active 入场动画的时间段 */
        /* v-levave-active 离场动画的时间段 */
        .v-enter-active,
        .v-levae-activue {
            transition: all 0.8s ease;
        }
    </style>
    
    <body>
        <div id="app">
            <input type="button" value="按钮" @click="flag=!flag">
            <transition>
                <h3 v-if="flag">标题三</h3>
            </transition>
        </div>
    
        <script src="./lib/vue-2.4.0.js"></script>
        <script>
            var vm = new Vue({
                el: '#app',
                data: {
                    flag: false
                },
                methods: {}
            })
        </script>
    </body>
    

    1.1.2 修改过渡类名前缀给多个元素设置动画

    若有多个元素需要设置不同的动画,如果使用同一种过渡类名,那么动画将是一致的,这时就需要修改过渡类名的前缀 + transitionname 属性来实现。

    <style>
        /* 自定义 v 前缀 */
        .my-enter,
        .my-leave-to {
            opacity: 0;
            transform: translateY(70px);        /*从上飞入*/
        }
    
        .my-enter-active,
        .my-leave-active {
            transition: all 0.8s ease;
        }
    </style>
    
    <body>
        <div id="app">
            <input type="button" value="按钮" @click="flag=!flag">
            <transition>
                <h3 v-if="flag">标题三</h3>
            </transition>
    
            <input type="button" value="按钮2" @click="flag2=!flag2">
            <transition name="my">
                <h1 v-if="flag2">标题一</h3>
            </transition>
        </div>
    
        <script src="./lib/vue-2.4.0.js"></script>
        <script>
            var vm = new Vue({
                el: '#app',
                data: {
                    flag: false,
                    flag2: false
                },
                methods: {}
            })
        </script>
    </body>
    

    1.2 第三方 CSS 动画库 animate

    1、导入动画类库:

    <link rel="stylesheet" type="text/css" href="./lib/animate.css">
    

    2、定义 transition 及属性:

    <transition
    	enter-active-class="fadeInRight"
        leave-active-class="fadeOutRight"
        :duration="{ enter: 500, leave: 800 }">
      	<div class="animated" v-show="isshow">动画哦</div>
    </transition>
    

    示例:

    <!DOCTYPE html>
    <html lang="">
    
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Title Page</title>
        <link rel="stylesheet" href="./lib/animate.css">
    </head>
    
    <body>
        <div id="app">
            <input type="button" value="按钮" @click="flag=!flag">
            <!-- 需求: 点击按钮,让 h3 显示,再点击,让 h3 隐藏 -->
            <!-- <transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut">
          <h3 v-if="flag">这是一个H3</h3>
        </transition> -->
    
            <!-- 使用 :duration="毫秒值" 来统一设置 入场 和 离场 时候的动画时长 -->
            <!-- <transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="200">
          <h3 v-if="flag" class="animated">这是一个H3</h3>
        </transition> -->
    
            <!-- 使用  :duration="{ enter: 200, leave: 400 }"  来分别设置 入场的时长 和 离场的时长  -->
            <transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="{ enter: 200, leave: 400 }">
                <h3 v-if="flag" class="animated">标题三</h3>
            </transition>
        </div>
    
        <script src="./lib/vue-2.4.0.js"></script>
        <script>
            var vm = new Vue({
                el: '#app',
                data: {
                    flag: false,
                },
                methods: {}
            })
        </script>
    </body>
    
    </html>
    

    参考文档:

    1.3 JavaScript 钩子函数

    可以在属性中声明 JavaScript 钩子,通过钩子函数可以实现 半场动画,所谓半场动画,即只有进入之前或离开时的动画,最常见的就是加入购物车的时候半场动画

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

    JS 中调用:

    // ...
    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) {
        // ...
      }
    }
    

    示例:

    利用 JavaScript 钩子函数实现小球半场动画,模拟加入购物车场景:

    <!DOCTYPE html>
    <html lang="">
    
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Title Page</title>
        <style>
            .ball {
                 15px;
                height: 15px;
                border-radius: 50%;
                background-color: red;
            }
        </style>
    </head>
    
    <body>
        <div id="app">
            <input type="button" value="按钮" @click="flag=!flag">
            <!-- 使用 transition 元素将小球包裹起来 -->
            <transition 
                @before-enter="beforeEnter" 
                @enter="enter" 
                @after-enter="afterEnter">
                <div class="ball" v-show="flag"></div>
            </transition>
        </div>
    
        <script src="./lib/vue-2.4.0.js"></script>
        <script>
            var vm = new Vue({
                el: '#app',
                data: {
                    flag: false,
                },
                methods: {
                    beforeEnter(el) {
                        // 动画入场之前,动画尚未开始,用于设置元素开始动画之前的起始样式
                        // 设置小球开始动画之前的起始位置
                        el.style.transform = "translate(0, 0)"      // 起始坐标
                    },
                    enter(el, done) {
                        el.offsetWidth      // el.offsetWidth 会强制动画刷新
                        
                        // 动画开始之后的样式,设置小球动画之后的,结束状态
                        el.style.transform = "translate(150px, 450px)"      // 结束坐标
                        el.style.transition = "all 1s ease"
    
                        done()      // 起始就是 afterEnter 这个函数,也就是说:done 是 afterEnter 函数的引用
                    },
                    afterEnter(el) {
                        // 动画完成后,隐藏小球,flag 初始值为 false,点击按钮后为 true,!flag 即为 false
                        this.flag = !this.flag
                    }
                }
            })
        </script>
    </body>
    
    </html>
    

    Tips:当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。

    参考文章:

    1.4 列表过渡

    目前为止,关于过渡动画我们已经了解了:

    • 单个节点
    • 同一时间渲染多个节点中的一个

    若要渲染整个列表,使用 <transition-group> 组件,组件特点:

    • <transition-group> 会模块渲染为一个 <span> 标签,若想渲染为其他标签,可以使用 tag 属性更换,如:tag="ul"
    • 内部元素需要提供唯一的 key 属性值
    • CSS 过渡类将会应用在内部元素中,而不是这个组/容器本身

    示例:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <link rel="stylesheet" href="./lib/bootstrap-3.3.7.css">
        <style>
            li {
                border: 1px dashed #999;
                margin: 5px;
                line-height: 35px;
                padding-left: 5px;
                font-size: 12px;
                 100%;
            }
    
            li:hover {
                background-color: hotpink;
                transition: all 0.8s ease;
            }
    
            /* 过渡开始状态,以及进入过渡的结束状态 */
            .v-enter,
            .v-leave-to {
                opacity: 0;
                transform: translateY(80px);
            }
    
            /* 进入过渡生效时的状态,离开过渡生效时的状态 */
            .v-enter-active,
            .v-leave-active {
                transition: all 0.6s ease;
            }
    
            /* 下面的 .v-move 和 .v-leave-active 配合使用,能够实现列表后续的元素,渐渐地漂上来的效果 */
            .v-move {
                transition: all 0.6s ease;
            }
    
            .v-leave-active {
                position: absolute;
            }
        </style>
    </head>
    
    <body>
        <div id="app">
            <div class="col-md-8">
                <div>
                    <label>
                        Id:
                        <input type="text" v-model="id">
                    </label>
    
                    <label>
                        Name:
                        <input type="text" v-model="name" @keyup.enter="add">
                    </label>
    
                    <input type="button" value="添加" @click="add">
                </div>
    
                <!-- 使用 transition-group 包裹要过渡的列表 -->
                <!-- v-for 循环创建元素,设置动画,且必须为每一个元素设置 :key 属性 -->
                <!-- appear 属性,实现页面展示时,入场时的结果 -->
                <transition-group appear tag="ul">
                    <li v-for="(item, i) in list" :key="item.id" @click="del(i)">
                        {{ item.id }} --- {{ item.name }}
                    </li>
                </transition-group>
    
            </div>
    
        </div>
    
        <script src="./lib/vue-2.4.0.js"></script>
        <script>
            var vm = new Vue({
                el: '#app',
                data: {
                    id: "",
                    name: "",
                    list: [
                        { id: 1, name: '赵高' },
                        { id: 2, name: '秦桧' },
                        { id: 3, name: '严嵩' },
                        { id: 4, name: '魏忠贤' }
                    ]
                },
                methods: {
                    add() {
                        this.list.push({ id: this.id, name: this.name })
                        this.id = this.name = ''
                    },
                    del(i) {
                        this.list.splice(i, 1)
                    }
                }
            })
        </script>
    </body>
    
    </html>
    

    参考文章:

  • 相关阅读:
    BZOJ 2212/BZOJ 3702
    BZOJ 4761 Cow Navigation
    BZOJ 3209 花神的数论题
    BZOJ 4760 Hoof, Paper, Scissors
    BZOJ 3620 似乎在梦中见过的样子
    BZOJ 3940 Censoring
    BZOJ 3942 Censoring
    BZOJ 3571 画框
    BZOJ 1937 最小生成树
    BZOJ 1058 报表统计
  • 原文地址:https://www.cnblogs.com/midworld/p/13611037.html
Copyright © 2011-2022 走看看