🥚第三库动画与框架的结合
Vue3过渡动画
1.认识动画
-
在开发中,如果我们要给一个组件的显示和消失添加动画,就可以增加用户体验
-
React是没有提供任何动画相关的API,但是vue中给我们提供好了一些内置的组件和对应的API来完成动画,利用它们我们可以方便的实现过渡动画效果
-
没有动画的情况下,整个内容的显示和隐藏会非常的生硬:
-
- 如果我们希望给单元素或者组件实现过渡动画,可以使用 transition 内置组件来完成动画;
- 下面我们通过一个小案例来开始学习
- App.vue
<template>
<div>
<button @click="isShow = !isShow">显示|隐藏</button>
<transition name="fade">
<h2 v-if="isShow">App.vue</h2>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
isShow:true
}
},
methods: {
toggle() {
this.isShow = !this.isShow
}
}
}
</script>
<style scoped>
.fade-enter-from,
.fade-leave-to {
opacity:0;
}
.fade-enter-to,
.fade-leave-from {
opacity:1
}
.fade-enter-active,
.fade-leave-active{
transition: all 0.5s ease;
}
</style>
2.Transition组件原理
- 我们会发现,Vue自动给h2元素添加了动画,这是啥原因呢
- 当插入或删除包含在 transition 组件中的元素时,Vue 将会做以下处理:
- 会自动探测目标元素是否应用了CSS过度或动画,如果有就在恰当时机添加/删除CSS类名;
- 如果tansition 组件提供了JS钩子函数,这些钩子函数将在恰当的时机被调用
- 如果没有找到JS钩子并且没有检测到CSS过度|动画,DOM插入,删除操作将会立即执行;
3.过渡动画class
- 我们会发现上面提到了很多个class,Vue就是帮助我们在这些class之间来回切换完成的动画
- v-enter-from:定义进入过渡的开始状态,在元素被插入之前生效,在元素被插入之后的的下一帧移除
- v-enter-active:定义进入过渡生效时的状态,在整个进入过渡的阶段中应用,在元素被插入之前生效, 在过渡或者动画完成之后移除,这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数
- v-enter-to:定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter-from 被移除),在过渡/ 动画完成之后移除。
- v-leave-from:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
- v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
- v-leave-to:离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave-from 被删除),在过渡/ 动画完成之后移除。
4.animation动画
不多说,直接上代码,其实就是换成了动画,还是一个样样🉐️
<template>
<button @click="isShow=isShow">
显示|隐藏
</button>
<transition name="fade">
<h2 v-if="isShow">放大🐸</h2>
</transition>
</template>
<script>
export default {
data() {
return {
isShow:true
}
}
}
</script>
<style scoped>
.fade-enter-active {
animation:bounce 0.5s ease;
}
.fade-leave-active {
animation bounce 0.5s ease reverse;
}
@keyframes bounce {
0% {
transform:scale(0)
}
50% {
transform:scale(1.5)
}
100% {
transform:scale(1)
}
}
</style>
5.同时设置过渡和动画
-
Vue为了知道过渡的完成,内部是在监听transitionend或animationend,到底使用那个取决于元素应用的规则
- 如果知识使用了其中一个,那么Vue能自动识别类型并设置监听
-
但如果同时使用会怎么样呢?
- 在这种情况下可能某一个动画执行结束时,另一个动画还没有结束
- 我们可以设置type属性为 animation 或者 transition来明确告知Vue监听的类型
-
👀以下代码示例:
<template>
<button @click="isShow=isShow">
显示|隐藏
</button>
<!-- 一般不会遇到这玩意,同时使用非常少,如果有也是设置type=时间动画长的那个 -->
<!--
duration第一种写法:duration="1000"
duration第二种写法:duration= {enter:800,leave:1000}
也是很少使用,但是要知道有这个属性
-->
<transition name="fade" type="animation" :duration="1000">
<h2 v-if="isShow">放大🐸</h2>
</transition>
</template>
<script>
export default {
data() {
return {
isShow:true
}
}
}
</script>
<style scoped>
.fade-enter-from,
.fade-leave-to {
opacity:0;
}
.fade-enter-active,
.fade-leave-active {
transition:opacity 0.5s ease;
}
.fade-enter-active {
animation:bounce 0.5s ease;
}
.fade-leave-active {
animation bounce 0.5s ease reverse;
}
@keyframes bounce {
0% {
transform:scale(0)
}
50% {
transform:scale(1.5)
}
100% {
transform:scale(1)
}
}
</style>
6.过渡模式
还是先从一段代码看起然后进行分析
<template>
<button @click="isShow=isShow">
显示|隐藏
</button>
<transition name="fade" mode="in-out">
<h2 v-if="isShow">放大🐸</h2>
<h2 v-else>井底之蛙,土黑娃</h2>
</transition>
</template>
<script>
export default {
data() {
return {
isShow:true
}
}
}
</script>
<style scoped>
.fade-enter-from,
.fade-leave-to {
opacity:0;
}
.fade-enter-active,
.fade-leave-active {
transition:opacity 0.5s ease;
}
.fade-enter-active {
animation:bounce 0.5s ease;
}
.fade-leave-active {
animation bounce 0.5s ease reverse;
}
@keyframes bounce {
0% {
transform:scale(0)
}
50% {
transform:scale(1.5)
}
100% {
transform:scale(1)
}
}
</style>
解释如下:
-
我们运行程序之后会发现一个问题:放大🐸 和 井底之蛙,土黑娃 是同时存在的
- 这是因为默认情况下进入和离开动画是同时发生的
-
但是我们不希望这么做,则需要设置transition得过渡模式:
- in-out:新元素先进行过渡,完成后当前元素过渡离开
- out-in:当前元素先进行过渡,完成后新元素过渡进入
还有一个点就是开发不仅仅是简单的标签切换,也有可能是组件的切换也可以使用过渡动画来进行包裹实现,我这里就不放代码了,如果有兴趣可以直接去这篇文章juejin.cn/post/715842…找到对应的动态组件代码结合本篇文章进行使用。还有如果appear设置了就代表默认就执行动画代码。意思就是一开始就执行动画
[注意⚠️] isShow? 'home' : 'about' 是对应的组件!(可以创建试试看哦)
7.animate.css
-
为什么要使用第三方库呢?不是已经有内置好的动画组件了?
- 其实🤔,使用内置的也可以,但是在开发阶段肯定是以效率为主,所以引用一些第三方库的动画库,比如animate.css,点我进入官网
-
那么什么是animate.css?
- Animate.css is a library of ready-to-use, cross-browser animations for use in your web projects. Great for emphasis, home pages, sliders, and attention-guiding hints.
-
如何使用这个库呢?
- 安装animate.css库
- 导入animate.css库的样式
- 使用animation动画或者animate提供的类
#安装
npm install animate.css --save
//在全局导入这个库的样式
import 'animate.css';
第一种方式1️⃣
<template>
<div class="app">
<button @click="isShow = !isShow">显示/隐藏</button>
<transition name="fade">
<h2 v-show="isShow">Animate.css</h2>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
isShow: true
}
}
}
</script>
<style scoped>
.fade-enter-active{
animation:fadeInRightBig 1s ease-in;
}
.fade-leave-active {
animation:fadeInRightBig 1s ease-in reverse;
}
</style>
第二种方式2️⃣:自定义过渡class
-
我们可以通过以下 attribute 来自定义过渡类名:
- enter-from-class
- enter-active-class
- enter-to-class
- leave-from-class
- leave-active-class
- leave-to-class
-
优先级高于普通的类名,这对于Vue的过渡系统和其他第三方css动画库,比如Animate.css结合使用
<template>
<div class="app">
<button @click="isShow = !isShow">显示/隐藏</button>
<!-- 这个就是使用自定义的class然后去官网复制对应的类粘贴在
这些自定义类里面就可以实现进入 或者出去 的动画效果-->
<!-- 还有这个animate_animated必须加上才会有效果 -->
<transition enter-active-class="animate__animated animate__bounce">
<h2 v-show="isShow">Animate.css</h2>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
isShow: true
}
}
}
</script>
<style scoped>
</style>
8.JavaScript钩子
- 在使用动画之前,我们先来看一下transition组件给我们提供的JavaScript钩子,这些钩子可以帮助我们监听动画执行到什么阶段了
- 当我们使用JS来执行过渡动画时,需要进行done回调,否则将会被同步调用,过渡会立即完成
- 添加:css="false",也会让Vue跳过css的jian ce,除了性能略高之外,这可以有效避免过渡中css规则的影响
- 意思就是说执行对应的动画的时候,比如from to这些就对应着beforeenter,beforeleave
- 通过下面👇这段代码进行查看
<template>
<div class="app">
<div><button @click="isShow = !isShow">显示/隐藏</button></div>
<transition @before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@enter-cancelled="enterCancelled"
@before-leave="beforeLeave"
@leave="leave"
@afterLeave="afterLeave"
@leave-cancelled="leaveCancelled"
:css="false">
<h2 class="title" v-if="isShow">Hello World</h2>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
isShow: true
}
},
methods: {
beforeEnter() {
console.log("beforeEnter");
},
enter() {
console.log("enter");
},
afterEnter() {
console.log("afterEnter");
},
enterCacelled() {
console.log("enterCacelled")
},
beforeLeave() {
console.log("beforeLeave");
},
leave() {
console.log("leave");
},
afterLeave() {
console.log("afterLeave");
}
leaveCancelled() {
console.log("leaveCancelled")
}
}
}
</script>
<style scoped>
.title {
display: inline-block;
}
</style>
9.gsap库
-
什么是gsap呢? 点击我进官网
- GSAP就是 GreenSock动画平台
- 非常强大,通过javascript给css属性,SVG,Canvas等设置动画,而且浏览器兼容的
-
如何使用这个库?
- 安装gsap
- 导入gsap库
- 使用提供的API
#安装gsap
npm install gsap
<template>
<div class="app">
<div><button @click="isShow = !isShow">显示/隐藏</button></div>
<transition @enter="enter"
@leave="leave"
:css="false">
<h2 class="title" v-if="isShow">Hello World</h2>
</transition>
</div>
</template>
<script>
import gsap from 'gsap';
export default {
data() {
return {
isShow: true,
}
},
methods: {
enter(el, done) {
console.log("enter");
gsap.from(el, {
scale: 0,
x: 200,
onComplete: done
})
},
leave(el, done) {
console.log("leave");
gsap.to(el, {
scale: 0,
x: 200,
onComplete: done
})
}
}
}
</script>
<style scoped>
.title {
display: inline-block;
}
</style>
9.1小案例
- 这个案例就是让数字一点点变化
<template>
<div class="app">
<input type="number" step="100" v-model="counter">
<h2>当前计数: {{showNumber.toFixed(0)}}</h2>
</div>
</template>
<script>
import gsap from 'gsap';
export default {
data() {
return {
counter: 0,
showNumber: 0
}
},
watch: {
counter(newValue) {
gsap.to(this, {duration: 1, showNumber: newValue})
}
}
}
</script>
<style scoped>
</style>
10.认识列表过渡transition-group
-
- 默认情况下,它不会渲染一个元素的包裹器,但是你可以指定一个元素并以 tag attribute 进行渲染;
- 过渡模式不可用,因为我们不再相互切换特有的元素;
- 内部元素总是需要提供唯一的 key attribute 值;
- CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身;
<template>
<button @click="addNum">添加数字</button>
<button @click="removeNum">删除数字</button>
<button @click="shuffleNum">数字洗牌</button>
<transition-group tag="p" name="fade">
<span v-for="item in numbers" :key="item" class="item">
{{item}}
</span>
</transition-group>
</template>
<script>
import _ from 'lodash';
export default {
data() {
return {
numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
numCounter: 10
}
},
methods: {
//随机位置添加
addNum() {
this.numbers.splice(this.randomIndex(),0,this.numCounter++)
},
//随机位置删除
removeNum() {
this.numbers.splice(this.randomIndex(),1)
},
//洗牌
shuffleNum() {
this.numbers = _.shuffle(this.numbers);
},
//随机值
randomIndex() {
return Math.floor(Math.random() * this.numbers.length)
}
}
}
</script>
<style scoped>
.item {
margin-right: 10px;
display: inline-block;
}
.fade-enter-from,
.fade-leave-to {
opacity:0
transform:translateY(30px)
}
.fade-enter-active,
.fade-leave-active {
transition:all 1s
}
/* 添加离场为绝对定位,防止离场动画bug */
.fade-leave-active {
position:absolute;
}
/* 以通过使用一个新增的 v-move 的class来完成移动动画 */
.fade-move {
transition:transform 1s ease;
}
</style>
10.1列表交替过渡案例
- 我们来通过gsap的延迟delay属性,做一个交替消失的动画:
<template>
<div>
<input v-model="keyword">
<transition-group tag="ul" name="fade" :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>
import gsap from 'gsap';
export default {
data() {
return {
names: ["abc", "cba", "nba", "why", "lilei", "hmm", "kobe", "james"],
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.index * 0.5,
onComplete: done
})
},
leave(el, done) {
gsap.to(el, {
opacity: 0,
height: 0,
delay: el.dataset.index * 0.5,
onComplete: done
})
}
}
}
</script>
<style scoped>
/* .fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 1s ease;
} */
</style>
11.做个小总结
- 这篇文章主要讲了Vue动画组件还有一些第三方的动画库配合使用
- 比如gsap和animate.css都可以实现一些动画效果吸引眼球
- 还有transition-group,和transition组件一些小细节
转载自:https://juejin.cn/post/7158777076839874568