前端之美-VueJsVue.js

Vue.js第4课-Vue中的动画特效(part01)

2019-05-19  本文已影响99人  e20a12f8855d

一、Vue 中的 css 动画原理

先来实现一个非常简单的功能,通过点击按钮控制文本的展示与否。

<div id="app">
    <button @click="clickFun">切换</button>
    <div v-if="show">Hello World!</div>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

下面,我想实现一个动画的功能,“Hello World!” 显示和隐藏的时候,能够有一个渐隐渐现的动画效果。首先需要在 “Hello World!” 这个 div 外层包裹一个 transition 标签,这个标签的意思是他包裹的元素有一个动画效果,可以给 transition 这个标签起一个名字,例如 name="fade",这个名字可以随意起。我们还要把 transition 过渡动画的原理讲清楚。

在进入/离开的过渡中,会有 6 个 class 切换,Vue.js 官方文档是这样描述这 6 个 class 的:

1、v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。

2、v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。

3、v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。

4、v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。

5、v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。

6、v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

根据上边的 class 我们可以给元素添加一下过渡的样式:

<style>
    /* 进入 */
    .fade-enter {
        opacity: 0
    }

    .fade-enter-active {
        transition: opacity 2s
    }
</style>

<div id="app">
    <button @click="clickFun">切换</button>
    <transition name="fade">
        <div v-if="show">Hello World!</div>
    </transition>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

上面代码,在第一次点击后,元素消失,再次点击,元素渐渐显示出来,可以看到控制台中给该元素添加了两个样式名,分别是 fade-enter-active 和 fade-enter-to,然后在 2s 后消失了,所以出现了渐现的效果。这两个 class 就是上边列出的 2 和 3 class。此时进入的过渡实现了,我们再添加一下离开的过渡。

<style>
    /* 进入 */
    .fade-enter {
        opacity: 0
    }

    .fade-enter-active {
        transition: opacity 2s
    }

    /* 离开 */
    .fade-leave-to {
        opacity: 0
    }

    .fade-leave-active {
        transition: opacity 2s
    }
</style>

<div id="app">
    <button @click="clickFun">切换</button>
    <transition name="fade">
        <div v-if="show">Hello World!</div>
    </transition>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

元素离开时,也被添加了两个 class,分别是 fade-leave-active 和 fade-leave-to,也就是上边列出的 5 和 6 class。

面代码就实现了一个渐隐渐现的动画效果。在 transition 也可以不传入 name,样式名中的 fade 换成 v 就可以,也可以把相同属性的样式放在一起:

<style>
    .v-enter,
    .v-leave-to {
        opacity: 0
    }

    .v-enter-active,
    .v-leave-active {
        transition: opacity 2s
    }
</style>

<div id="app">
    <button @click="clickFun">切换</button>
    <transition>
        <div v-if="show">Hello World!</div>
    </transition>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

二、在 Vue 中使用 Animate.css 库

这一节来讲解 Vue 中更复杂的动画效果。首先进入上一节最终的那段代码,并对这段代码进行一个变更。上一节是讲了 transition 的使用方法,这一节看一下 keyframes 形式的动画。

回忆一下 fade-enter-active 和 fade-leave-active 这两个 class 是什么时候生效的,当 div 标签在显示的这个过程中,fade-enter-active 是一直存在的,当他在隐藏的过程中,fade-leave-active 是一直存在的,根据这个特性可以这样写动画效果:

<style>
    @keyframes bounce-in {
        0% {
            transform: scale(0);
        }

        50% {
            transform: scale(1.5);
        }

        100% {
            transform: scale(1);
        }
    }

    .fade-enter-active {
        transform-origin: left center;
        animation: bounce-in 1s;
    }

    .fade-leave-active {
        transform-origin: left center;
        animation: bounce-in 1s reverse;
    }
</style>
<div id="app">
    <button @click="clickFun">toggle</button>
    <transition name="fade">
        <div v-if="show">Hello World!</div>
    </transition>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

上面代码定义了一个 keyframes 的一个 CSS3 动画 bounce-in,分别设置 0%、50%、100% 时 的状态,然后在 fade-enter-active 和 fade-leave-active 中就可以用这个动画了。打开页面可以看到,点击 toggle,隐藏时候有放大缩小的效果,显示的时候也有放大缩小的效果。

上面就讲解了在 Vue 中如何使用 keyframes 这种形式的 CSS3 动画。接着再讲一个知识点,当你使用 transition 标签的时候,给了一个 name="fade",那么他就会都自动的添加 fade-enter-active 和 fade-leave-active 这样的 class 名字。那我能不能定义一个就叫 enter 或 leave 这样的一个名字,不用他默认提供的命名的规范?是可以的,如果想这么写,只需要在 transition 外面自定义这个 class 名字,如下面代码:

<style>
    @keyframes bounce-in {
        0% {
            transform: scale(0);
        }

        50% {
            transform: scale(1.5);
        }

        100% {
            transform: scale(1);
        }
    }

    .enter {
        transform-origin: left center;
        animation: bounce-in 1s;
    }

    .leave {
        transform-origin: left center;
        animation: bounce-in 1s reverse;
    }
</style>
<div id="app">
    <button @click="clickFun">change</button>
    <transition name="fade" enter-active-class="enter" leave-active-class="leave">
        <div v-if="show">Hello World!</div>
    </transition>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

可以看到效果是一样的,不会有任何问题,到这里就可以知道,其实你可以自定义添加的 class 名字。

现在既然可以自定义 fade-enter-active 和 fade-leave-active 名字,那借助这个功能我们就可以在我们的 Vue 项目里使用比较流行的 animate.css 库了,我们可以进入 animate.css 官网,在这里去查看对应动画的 class 名,然后添加 class 名。

下载 animate.css 文件并引用,我直接用了 BootCDN 的方式在项目中引用了 animate.css。引用了 animate.css 我就不需要自己写动画效果了,然后在入场动画和出场动画的 class 中添加 animated,并在后边更上对应动画效果的 class 名,例如下面代码:

<link href="https://cdn.bootcss.com/animate.css/3.7.0/animate.css" rel="stylesheet">
<div id="app">
    <button @click="clickFun">change</button>
    <transition name="fade" enter-active-class="animated bounce" leave-active-class="animated flash">
        <div v-if="show">Hello World!</div>
    </transition>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

如果想使用 animate.css 这个库,有几点需要注意:第一点是你必须使用自定义 class 名字的形式来使用 animate.css,第二是 class 类里面必须得包含一个 animate 这样一个具体的类,然后根据需求的不同添加不同动画的类名。

三、在 Vue 中同时使用过渡和动画

我们在上一节最终的代码上看一下,注意要引入 animate.css。使用 animate.css 和 @keyframes 是没有区别的,animate.css 其实就是一个封装。

<div id="app">
    <button @click="clickFun">toggle</button>
    <transition name="fade" enter-active-class="animated swing" leave-active-class="animated flash">
        <div v-if="show">Hello World!</div>
    </transition>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

当我们打开页面的时候,也就是元素第一次显示的时候,其实这个动画并没有被添加上,点击之后才会被添加上。那如果我想在元素第一次显示的时候,我的这个 “Hello Word!” 也具备动画效果,应该怎么做呢?

我们在 transition 中增加一个自定义名字叫做 appear-active-class="animated swing",就这样写是不行的,如果想使用 appear-active-class 的话,记得在上面再写一个属性叫做 appear,意思是第一次显示这个内容的时候,也有一个动画效果,它的动画效果是使用了 animated 库中的一个动画。

<div id="app">
    <button @click="clickFun">toggle</button>
    <transition name="fade" appear enter-active-class="animated swing" leave-active-class="animated jello"
        appear-active-class="animated jello">
        <div v-if="show">Hello World!</div>
    </transition>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

这个时候刷新页面,可以看到第一次显示元素的时候就有一个动画效果,隐藏没问题,显示也没问题,都有动画效果。

在上面这个例子中,实际上我们只用到了一种动画,就是 animate.css 库提供的动画。假设入场动画不仅有 css3 的动画效果,还有一个过渡的动画效果,怎么做呢?

在 enter-active-class 中添加一个 fade-enter-active,在 leave-active-class 中添加一个 fade-leave-active,然后给新添加的这两个 class 名添加属性,回忆一下第一节添加 transition 的方法。

<style>
    .fade-enter,
    .fade-leave-to {
        opacity: 0;
    }

    .fade-enter-active,
    .fade-leave-active {
        transition: opacity 3s;
    }
</style>
<div id="app">
    <button @click="clickFun">toggle</button>
    <transition name="fade" appear enter-active-class="animated swing fade-enter-active"
        leave-active-class="animated jello fade-leave-active" appear-active-class="animated swing">
        <div v-if="show">Hello World!</div>
    </transition>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

打开页面点击按钮可以看到,此时元素既有 animate 动画效果,也有 transition 透明度的变化效果,所以把两个动画结合到了一起做了一个使用。

但是会发现这样一个问题,opacity 动画执行的是 3s,但是 animate.css 这个动画执行的是几秒呢?我们可以从 animate.css 源码中查看一下:

可以看到 animate.css 动画执行的时间是 1s,那整个的动画效果到底是怎么算呢?是 1s 所有动画都结束,还是 3s 所有动画都结束?Vue 也不清楚哪一个是结束时长,这个时候我们可以手动的去设置,我们现在已 3s 这个比较长的时间作为动画时间,直接在 transition 标签中写 type="transition" 就可以了:

<style>
    .fade-enter,
    .fade-leave-to {
        opacity: 0;
    }

    .fade-enter-active,
    .fade-leave-active {
        transition: opacity 3s;
    }
</style>
<div id="app">
    <button @click="clickFun">toggle</button>
    <transition type="transition" name="fade" appear enter-active-class="animated swing fade-enter-active"
        leave-active-class="animated jello fade-leave-active" appear-active-class="animated swing">
        <div v-if="show">Hello World!</div>
    </transition>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

它的意思是,我的这个动画既有 animate 就是普通的这种 @keyframe 形式的动画,又有 transition 这种形式的动画,我的动画时长以 transition 的动画时长为准,他就会以 3s 作为整个动画的执行时间。到页面上,点击按钮,可以看到 3s 动画结束。这样我们就确定了我们动画的播放时长。

现在是以过渡效果的时长作为动画的总时长,那能不能我自己定义一个动画执行的总时长呢?这个时长是可以进行自定义的,可以在 transition 标签中这么写:

<style>
    .fade-enter,
    .fade-leave-to {
        opacity: 0;
    }

    .fade-enter-active,
    .fade-leave-active {
        transition: opacity 3s;
    }
</style>
<div id="app">
    <button @click="clickFun">toggle</button>
    <transition :duration="5000" name="fade" appear enter-active-class="animated swing fade-enter-active"
        leave-active-class="animated jello fade-leave-active" appear-active-class="animated swing">
        <div v-if="show">Hello World!</div>
    </transition>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

上面代码,我在 transition 标签中添加了一个 :duration 属性,值设置为 5000,意思是我让这个动画的执行时长是 5s。回到浏览器上,怎么才能看到效果呢?我们可以查看元素,点击 toggle,3s 后元素其实已经隐藏掉了,但是这个动画并没有执行完,fade-leave-active 和 fade-leave-to 还都在,等 5s 后才会消失。

现在是自定义了一个动画的时长,其实这个时长还可以设置的复杂一点,可以设置一个入场动画的时长和一个出场动画的时长,例如入场设置为 5s,出场设置为 10s。

<style>
    .fade-enter,
    .fade-leave-to {
        opacity: 0;
    }

    .fade-enter-active,
    .fade-leave-active {
        transition: opacity 3s;
    }
</style>
<div id="app">
    <button @click="clickFun">toggle</button>
    <transition :duration="{enter:5000,leave:10000}" name="fade" appear
        enter-active-class="animated swing fade-enter-active" leave-active-class="animated jello fade-leave-active"
        appear-active-class="animated swing">
        <div v-if="show">Hello World!</div>
    </transition>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            clickFun: function () {
                this.show = !this.show
            }
        }
    })
</script>

打开页面,点击按钮,查看元素,可以看到元素入场的时长为 5s,出场的时长为 10s。


长得好看的都会关注我的 o(≧v≦)o~~

上一篇下一篇

猜你喜欢

热点阅读