首页 > 编程笔记 > JavaScript笔记
Vue transtion实现过渡动画效果(非常详细)
Vue 在插入、更新或者移除 DOM 时,提供了多种不同方式的应用过渡效果,包括:
为什么网页需要添加过渡和动画效果呢?因为过渡和动画效果能够提高用户的体验,帮助用户更好地理解页面中的功能。
本节重点学习用 transition 组件实现过渡和动画效果。
图 1 没有过渡效果
当单击按钮时,会发现 p 标签出现或者消失,但没有过渡效果,用户体验不太好。可以使用 Vue 的 transition 组件来实现消失或者隐藏的过渡效果。使用 Vue 过渡的时候,首先把过渡的元素添加到 transition 组件中。其中 .v-enter、.v-leave-to、.v-enter-active 和 .v-leave-active 样式是定义动画的过渡样式。
【实例】添加 CSS 过渡效果。
图 2 过渡效果
然后过渡到初始的位置,如下图所示。
图 3 显示内容
一个过渡效果包括两个阶段:一个是进入动画(Enter);另一个是离开动画(Leave)。
进入动画包括 v-enter、v-enter-to 两个时间点和 v-enter-active 一个时间段。离开动画包括 v-leave、v-leave-to 两个时间点和 v-leave-active 一个时间段。具体如下图所示:
图 4 过渡动画的时间点
定义过渡时,首先使用 transition 元素把需要被过度控制的元素包裹起来,然后自定义两组样式来控制 transition 内部的元素实现过渡。对于这些在过渡中切换的类名来说,如果使用一个没有名字的 <transition>,则 v- 是这些类名的默认前缀。
前面示例中定义的样式,在所有动画中会公用,transition 有一个 name 属性,可以通过它来修改过渡样式的名称。如果使用了 <transition name="my-transition">,那么 v-enter 会替换为 my-transition-enter。这样做的好处是区分每个不同的过渡和动画。
下面通过一个按钮来触发两个过渡效果,一个从右侧 150px 的位置开始,一个从下面 200px 的位置开始。
【实例】多个过渡效果。
图 5 多个过渡效果图
最终状态如下图所示:
图 6 最终状态
CSS动画的用法如下。
图 7 CSS动画效果
它们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库(如 Animate.css)的结合使用十分有用。
下面的示例在 transition 组件中使用 enter-active-class 和 leave-active-class 类,结合 animate.css 动画库实现动画效果。
【实例】自定义过渡的类名。
图 8 进入动画效果
再次单击“早春”按钮,触发离开动画,效果如图 9 所示。
图 9 离开动画效果
图 10 进入动画效果
再次单击“雪晴晚望”按钮,离开动画,效果如下图所示。
图 11 离开动画效果
Velocity 动画的配置选项如下:
- 在 CSS 过渡和动画中自动应用 class。
- 可以配合使用第三方 CSS 动画库,如 Animate.css。
- 在过渡钩子函数中使用 JavaScript 直接操作 DOM。
- 可以配合使用第三方 JavaScript 动画库,如 Velocity.js。
为什么网页需要添加过渡和动画效果呢?因为过渡和动画效果能够提高用户的体验,帮助用户更好地理解页面中的功能。
本节重点学习用 transition 组件实现过渡和动画效果。
transition组件
Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡:- 条件渲染(使用 v-if)。
- 条件展示(使用 v-show)。
- 动态组件。
- 组件根节点。
1) CSS过渡
常用的过渡都是使用 CSS 过渡。下面是一个没有使用过渡效果的示例,通过一个按钮控制 p 元素显示和隐藏。<div id="app"> <button v-on:click="show = !show"> 上京即事五首·其一 </button> <p v-if="!show">大野连山沙作堆,白沙平处见楼台。</p> <p v-if="!show">行人禁地避芳草,尽向曲阑斜路来。</p> </div> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ show:true } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在 Chrome 浏览器中运行程序,单击按钮后的效果如下图所示。
图 1 没有过渡效果
当单击按钮时,会发现 p 标签出现或者消失,但没有过渡效果,用户体验不太好。可以使用 Vue 的 transition 组件来实现消失或者隐藏的过渡效果。使用 Vue 过渡的时候,首先把过渡的元素添加到 transition 组件中。其中 .v-enter、.v-leave-to、.v-enter-active 和 .v-leave-active 样式是定义动画的过渡样式。
【实例】添加 CSS 过渡效果。
<style> /*v-enter-active入场动画的时间段*/ /*v-leave-active离场动画的时间段*/ .v-enter-active, .v-leave-active{ transition: all .5s ease; } /*v-enter是一个时间点,是进入之前元素的起始状态,此时还没有进入*/ /*v-leave-to是一个时间点,是动画离开之后,离开的终止状态,此时元素动画已经结束*/ .v-enter, .v-leave-to{ opacity: 0.2; transform:translateY(200px); } </style> <div id="app"> <button v-on:click="show = !show"> 古诗欣赏 </button> <transition> <p v-if="!show">鸿雁长飞光不度,鱼龙潜跃水成文。</p> </transition> </div> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ show:true } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在 Chrome 浏览器中运行程序,单击“古诗欣赏”按钮,可以发现,p 元素刚开始在下侧 200px 的位置开始,透明度为 0.2,如下图所示:
图 2 过渡效果
然后过渡到初始的位置,如下图所示。
图 3 显示内容
2) 过渡的类名
在进入/离开的过渡中,会有 6 个 class 切换:- v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
- v-enter-to:定义进入过渡的结束状态。在元素被插入之后的下一帧生效(与此同时 v-enter 被移除),在过渡/动画完成之后移除。
- v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间、延迟和曲线函数。
- v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
- v-leave-to:定义离开过渡的结束状态。在离开过渡被触发之后的下一帧生效(与此同时v-leave被删除),在过渡/动画完成之后移除。
- v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间、延迟和曲线函数。
一个过渡效果包括两个阶段:一个是进入动画(Enter);另一个是离开动画(Leave)。
进入动画包括 v-enter、v-enter-to 两个时间点和 v-enter-active 一个时间段。离开动画包括 v-leave、v-leave-to 两个时间点和 v-leave-active 一个时间段。具体如下图所示:
图 4 过渡动画的时间点
定义过渡时,首先使用 transition 元素把需要被过度控制的元素包裹起来,然后自定义两组样式来控制 transition 内部的元素实现过渡。对于这些在过渡中切换的类名来说,如果使用一个没有名字的 <transition>,则 v- 是这些类名的默认前缀。
前面示例中定义的样式,在所有动画中会公用,transition 有一个 name 属性,可以通过它来修改过渡样式的名称。如果使用了 <transition name="my-transition">,那么 v-enter 会替换为 my-transition-enter。这样做的好处是区分每个不同的过渡和动画。
下面通过一个按钮来触发两个过渡效果,一个从右侧 150px 的位置开始,一个从下面 200px 的位置开始。
【实例】多个过渡效果。
<style> .v-enter-active, .v-leave-active { transition: all 0.5s ease; } .v-enter, .v-leave-to{ opacity: 0.2; transform:translateX(150px); } .my-transition-enter-active, .my-transition-leave-active { transition: all 0.8s ease; } .my-transition-enter, .my-transition-leave-to{ opacity: 0.2; transform:translateY(200px); } </style> <div id="app"> <button v-on:click="show = !show"> 出郊 </button> <transition> <p v-if="!show">高田如楼梯,平田如棋局。</p> </transition> <transition name="my-transition"> <p v-if="!show">白鹭忽飞来,点破秧针绿。</p> </transition> </div> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ show:true } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在 Chrome 浏览器中运行程序,单击“出郊”按钮,触发两个过渡效果,如下图所示:
图 5 多个过渡效果图
最终状态如下图所示:
图 6 最终状态
3) CSS动画
CSS 动画的用法与 CSS 过渡差不多,区别是在动画中,v-enter 类名在节点插入 DOM 后不会立即删除,而是在 animationend 事件触发时删除。CSS动画的用法如下。
<style> /*进入动画阶段*/ .my-enter-active { animation: my-in .5s; } /*离开动画阶段*/ .my-leave-active { animation: my-in .5s reverse; } /*定义动画my-in*/ @keyframes my-in { 0% { transform: scale(0); } 50% { transform: scale(1.5); } 100% { transform: scale(1); } } </style> <div id="app"> <button @click="show = !show">对雪</button> <transition name="my"> <p v-if="show">六出飞花入户时,坐看青竹变琼枝。如今好上高楼望,盖尽人间恶路岐。</p> </transition> </div> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ show:true } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在 Chrome 浏览器中运行程序,单击“对雪”按钮时,触发 CSS 动画,效果如下图所示:
图 7 CSS动画效果
4) 自定义过渡的类名
可以通过以下 attribute 来自定义过渡的类名:- enter-class。
- enter-active-class。
- enter-to-class。
- leave-class。
- leave-active-class。
- leave-to-class。
它们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库(如 Animate.css)的结合使用十分有用。
下面的示例在 transition 组件中使用 enter-active-class 和 leave-active-class 类,结合 animate.css 动画库实现动画效果。
【实例】自定义过渡的类名。
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css"> <div id="app"> <button @click="show = !show"> 早春 </button> <!--enter-active-class:控制动画的进入--> <!--leave-active-class:控制动画的离开--> <!--animated 类似于全局变量,它定义了动画的持续时间--> <!--bounceInUp和slideInRight是动画具体的动画效果的名称,可以选择任意的效果--> <transition enter-active-class="animated bounceInUp" leave-active-class="animated slideInRight" > <p v-if="show">春销不得处,唯有鬓边霜。</p> </transition> </div> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ show:true } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在浏览器运行,单击“早春”按钮,触发进入动画,效果如下图所示:
图 8 进入动画效果
再次单击“早春”按钮,触发离开动画,效果如图 9 所示。
图 9 离开动画效果
5) 动画的JavaScript钩子函数
可以在 <transition> 组件中声明 JavaScript 钩子,它以属性的形式存在。例如下面的代码:<transition 进入动画钩子函数 :before-enter表示动画入场之前,此时动画还未开始,可以在其中设置元素开始动画之前的起始样式 v-on:before-enter="beforeEnter" :enter表示动画,开始之后的样式,可以设置完成动画的结束状态 v-on:enter="enter" :after-enter表示动画完成之后的状态 v-on:after-enter="afterEnter" :enter-cancelled用于取消开始动画的 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>然后在 Vue 实例的 methods 选项中定义钩子函数的方法:
<script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ show:true } }, 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) { ... } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>这些钩子函数可以结合 CSS transitions/animations 使用,也可以单独使用。
下面使用 velocity.js 动画库结合动画钩子函数来实现一个简单示例。当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。对于仅使用 JavaScript 过渡的元素,推荐添加 v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。
<!--Velocity和jQuery.animate 的工作方式类似,也是用来实现JavaScript动画的一个很棒的选择 --> <script src="velocity.js"></script> <div id="app"> <button @click="show = !show"> 雪晴晚望 </button> <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:leave="leave" v-bind:css="false" > <p v-if="show"> 野火烧冈草,断烟生石松。 </p> </transition> </div> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ show:false } }, methods: { // 进入动画之前的样式 beforeEnter: function (el) { // 注意:动画钩子函数的第一个参数:el,表示要执行动画的那个DOM元素, // 是一个原生的JS DOM对象 // 可以认为,el是通过document.getElementById('')方式获取到原生JS DOM对象的 el.style.opacity = 0; el.style.transformOrigin = 'left'; }, // 进入时的动画 enter: function (el, done) { Velocity(el, { opacity: 1, fontSize: '2em' }, { duration: 300 }); Velocity(el, { fontSize: '1em' }, { complete: done }); }, //离开时的动画 leave: function (el, done) { Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 }); Velocity(el, { rotateZ: '100deg' }, { loop: 5 }); Velocity(el, { rotateZ: '45deg', translateY: '30px', translateX: '30px', opacity: 0 }, { complete: done }) } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在 Chrome 浏览器中运行程序,单击“雪晴晚望”按钮,进入动画,效果如下图所示:
图 10 进入动画效果
再次单击“雪晴晚望”按钮,离开动画,效果如下图所示。
图 11 离开动画效果
Velocity 动画的配置选项如下:
duration:400, //动画执行时间 easing: "swing", //缓动效果 queue: "", //队列 begin:undefined, //动画开始时的回调函数 progress: undefined, //动画执行中的回调函数(该函数会随着动画的执行不断被触发) complete: undefined, //动画结束时的回调函数 display: undefined, //动画结束时设置元素的css display属性 visibility: undefined, //动画结束时设置元素的css visibility属性 loop: false, //循环次数 delay: false, //延迟 mobileHA: true //移动端硬件加速(默认开启)