14.Vue3过渡和动画实现
1.认识动画
给组件显示和消失添加某种过渡动画,可以增加用户体验。
react本身不提供任何动画相关的API,需要使用第三方库react-transition-group
Vue提供一些内置组件和对应的API来完成动画,可以方便实现过渡动画效果。
<button @click="isshow=!isshow">显示/隐藏</button>
<h2 v-if="isshow">Hello World</h2>
没有动画的情况下,内容显示或隐藏会非常生硬,给单元素或者组件实现过渡动画,可以使用transition内置组件
。
将要实现动画的单个元素或者组件嵌套再transition中,设置name。
<transition name="anima">
<h2 v-if="isshow">Hello World</h2>
</transition>
在样式中设置过渡:
<style scoped>
.anima-enter-from,
.anima-leave-to{
opacity: 0;
}
.anima-leave-from,
.anima-enter-to{
opacity: 1;
}
.anima-enter-active,
.anima-leave-active{
transition: opacity 2s ease;
}
</style>
2.transition组件的原理
当插入或删除包含在transition组件的元素中时,vue将会做以下处理:
1.自动嗅探目标元素是否应用了CSS过渡或者动画,如果有,那么在恰当的时机添加/删除 CSS类名;
2.如果transition组件提供了JavaScript钩子函数,这些钩子函数在恰当的时机会被调用;
3.如果没有找到JavaScript钩子并且也没有检测到CSS过渡/动画,DOM插入、删除操作将会立即执行。
class的命名规则
如果我们使用的是一个没有name的transition,class的命名以v-
作为默认前缀。
如果我们添加了一个name属性,例如:<transition name="anima">
那么class以anima-
开头
3.过渡CSS动画
<style scoped>
.pho{
display: block;
}
.anima-enter-active{
animation: anima-in 1s ;
}
.anima-leave-active{
animation: anima-in 1s reverse;
}
@keyframes anima-in{
0%{
transform: scale(0);
},
50%{
transform: scale(1.2);
},
100%{
transform: scale(1);
}
}
</style>
同时设置过渡和动画
会出现一种情况第一个动画执行结束之后,另一个动画还没有结束,在这种情况下我们可以设置type属性为animation或者transition来告诉Vue监听的类型。
<transition name="anima" type="transition">
通常是谁的时间长监听谁。
过渡模式的mode
动画在两个元素之间来回切换时,会有同时存在的问题
默认情况下进入和离开动画是同时发生的;
解决:mode="out-in"
先出去再进来mode="in-out"
先进来后出去
第一次进入页面时就让元素有动画效果<transition name="anima" appear="true">
appear默认情况下为false。
4.结合第三方库使用动画animate.css
认识animate.css
是一个为我们的web项目已经准备好的、跨平台的动画库,对于强调、主页、滑动、注意力引到非常有用。
如何使用animate.css库
- 安装animate.css库
npm install animate.css
- 导入animate.css库(在main.js中)
import "animate.css"
- 使用animate动画或者animate提供的类;
在官网中选择要使用的动画效果:
在样式中使用
.anima-enter-active{
animation: backInUp 1s ease-in;
}
.anima-leave-active{
animation: backInDown 1s ease-in;
}
transition结合animate.css的使用:
<transition name="anima" enter-active-class="animate__animated animate__backInUp"
leave-active-class="animate__animated animate__backInDown">
<h2 class="pho" v-if="isshow">Hello World</h2>
</transition>
在class里必须要有animate__animated
才能使用其他样式,动画样式的名字在官网复制,点击这个复制按钮即可。
5.认识gsap库
通过JavaScript来实现动画效果,可以使用gsap库。
gsap(GreenSock Animation Platform)的缩写;
通过JavaScript为CSS属性、SVG、Canvas设置动画。
如何使用?
安装gsap库;npm install gsap
导入gsap库;import gsap from "gsap";
使用对应的API即可。
transition 组件提供了些钩子函数@before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter" @before-leave="beforeLeave" @leave="leave" @after-leave="afterLeave"
可与在method中使用这些函数:
methods: {
enter(el, done) {
gsap.from(el,{
scale:0,
x:200,
onComplete:done
})
},
leave(el,done) {
gsap.to(el,{
scale:0,
x:200,
onComplete:done
})
}
}
在transition组件标签中添加:css="false"
,会让vue跳过CSS的检测,避免过渡过程中CSS规则的影响。
5.列表的过渡
如果渲染的是一个列表,并且该列表中添加删除数据也希望有动画执行,可以用内置组件<transition-group>
组件来完成.
特点:
不会渲染一个元素的包裹器,可以指定元素并以tag 属性渲染;
过渡模式不可以用(mode);
内部元素需要提供唯一的key值;
CSS过渡的类将会应用在内部的元素中,而不是这个组件/容器本身.
<!-- 案例,列表添加删除元素带有动画效果 -->
<template>
<div>
<button @click="addNum">添加数字</button>
<button @click="removeNum">删除数字</button>
<button @click="shuffleNum">数字洗牌</button>
<transition-group tag="p" name="donghua">
<span class="items" v-for="item in numbers" :key="item">{{item}}</span>
</transition-group>
</div>
</template>
<script>
// npm install lodash 下载库
import _ from "lodash"
export default{
data(){
return{
numbers:[0,1,2,3,4,5,6,7,8,9],
addcounter: 10
}
},
methods:{
addNum(){
this.numbers.splice(this.NumberIndex(), 0, this.addcounter ++)
},
removeNum(){
this.numbers.splice(this.NumberIndex(), 1)
},
shuffleNum(){
this.numbers=_.shuffle(this.numbers)
},
// 获取随机数
NumberIndex(){
return Math.floor(Math.random()*this.numbers.length);
}
}
}
</script>
<style scoped>
.items{
display:inline-block;
margin-left: 5px;
}
.donghua-enter-from,
.donghua-leave-to{
opacity: 0;
transform: translateY(50px);
}
.donghua-enter-active,
.donghua-leave-active{
transition: all 1s ease;
}
.donghua-leave-active{
position: absolute;
/* 绝对定位,元素移除时不占位 */
}
.donghua-move{
transition: transform 1s ease;
}
</style>
案例二:
<template>
<div>
<input v-model="keyword">
<!-- 用钩子函数实现交替动画 -->
<transition-group tag="ul" name="donghua" :css="false"
@before-enter="beforeEnter"
@enter="enter"
@leave="leave">
<li v-for="(item ,index) in showNames" :key="item" :data-index="index">
{{item}}
</li>
</transition-group>
</div>
</template>
<script>
// 导入gsap库
import gsap from "gsap";
export default{
data(){
return{
names:["lily","hmm","dazhu","xwang","jony","baby","kobe"],
keyword:""
}
},
// 使用计算属性过滤
computed:{
showNames(){
return this.names.filter(item => item.indexOf(this.keyword) !== -1)
}
},
methods:{
beforeEnter(el){
el.style.opacity=0;
el.style.height = 0;
},
enter(el,done){
gsap.to(el,{
opacity:1,
height:"1.5em",
delay: el.dataset * 0.5,
onComplete :done
})
},
leave(el,done){
gsap.to(el,{
opacity:0,
height:0,
delay: el.dataset * 0.5,
onComplete :done
})
}
}
}
</script>
<style scoped>
.donghua-enter-from,
.donghua-leave-to{
opacity: 0;
}
.donghua-enter-active,
.donghua-leave-active{
transition: all 1s ease;
}
.donghua-leave-active{
position: absolute;
/* 绝对定位,元素移除时不占位 */
}
.donghua-move{
transition: transform 1s ease;
}
</style>