Vue中的动画
单元素/组件动画
使用transition
标签进行包裹的元素就是要执行动画的元素,transition
是Vue封装的组件,可使用v-if
、v-show
以及动态组件
-
入场动画:
- 第一帧会自动为要执行动画的元素添加
.v-enter
和.v-enter-active
两个类名 - 第二帧会将
.v-enter
去除,并添加.v-enter-to
类名 - 动画结束会将
.v-enter-to
和.v-enter-active
两个类名去除
- 第一帧会自动为要执行动画的元素添加
-
出场动画:
- 第一帧会自动为要执行动画的元素添加
.v-leave
和.v-leave-active
两个类名 - 第二帧会将
.v-leave
去除,并添加.v-leave-to
类名 - 动画结束会将
.v-leave-to
和.v-leave-active
两个类名去除
- 第一帧会自动为要执行动画的元素添加
也就是说,.v-enter
和.v-leave
为动画前的状态,.v-enter-to
和.v-leave-to
为动画后的状态,.v-enter-active
和.v-leave-active
为动画(监听过渡)
可为transition
定义name
属性来修改类名的前缀,若不定义name
属性则会默认以v
作为前缀
过渡
- 入场过渡只要实现
.v-enter
和.v-enter-active
,动画会平滑从入场状态过渡到原本状态(.v-enter-to
就是元素原本状态,所以可省) - 出场过渡只要实现
.v-leave-to
和.v-leave-active
,动画会平滑从原本状态过渡到出场状态(.v-leave
就是元素原本状态,所以可省)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
<style>
.v-enter{
opacity: 0;
}
.v-leave-to{
opacity: 0;
}
.v-enter-active,
.v-leave-active{
transition: all 1s;
}
</style>
</head>
<body>
<div id="app">
<button @click="clickHandle">按钮</button>
<transition>
<h1 v-show="show">要执行动画的元素</h1>
</transition>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app",
data(){ return { show: true } },
methods: { clickHandle(){ this.show = !this.show } }
});
</script>
</body>
</html>
帧动画
自定义帧动画
- 入场动画只需要在
.v-enter-active
中调用帧动画即可 - 出场动画只需要在
.v-leave-active
中调用帧动画即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
<style>
@keyframes anim{
0%{
opacity: 0;
}
100%{
opacity: 1;
}
}
.v-enter-active{
animation: anim 1s;
}
.v-leave-active{
animation: anim 1s reverse;
}
</style>
</head>
<body>
<div id="app">
<button @click="clickHandle">按钮</button>
<transition>
<h1 v-show="show">自定义帧动画</h1>
</transition>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app",
data(){ return { show: true } },
methods: { clickHandle(){ this.show = !this.show } }
});
</script>
</body>
</html>
animate.css
将入场动画.v-enter-active
和出场动画.v-leave-active
自定义为animate.css库中的类名即可
- 要想使animate.css中的帧动画生效必须加
animated
类- animate.css的4.0版本中又将所有的类名增加了
animate__
的前缀(两个短横线)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
<style>
@keyframes anim{
0%{ opacity: 0; }
100%{ opacity: 1; }
}
.enter{
animation: anim 1s;
}
.leave{
animation: anim 1s reverse;
}
</style>
</head>
<body>
<div id="app">
<button @click="clickHandle">按钮</button>
<transition enter-active-class="enter" leave-active-class="leave">
<!-- 可使用xxx-class属性自定义要添加的类名 -->
<h1 v-show="show">自定义帧动画</h1>
</transition>
<transition
appear
appear-active-cliss="animate__animated animate__backInDown"
enter-active-class="animate__animated animate__backInDown"
leave-active-class="animate__animated animate__backOutDown">
<h1 v-show="show">Animate.css</h1>
<!-- appear和appear-active-cliss用于元素首次出现时的动画效果 -->
</transition>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app",
data(){ return { show: true } },
methods: { clickHandle(){ this.show = !this.show } }
});
</script>
</body>
</html>
同时使用过渡和帧动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
<style>
.v-enter,
.v-leave-to{
opacity: 0;
}
.v-enter-active,
.v-leave-active{
transition: all 0.5s;
}
</style>
</head>
<body>
<div id="app">
<button @click="clickHandle">按钮</button>
<h2>
在添加上原来的v-enter-active和v-leave-active类即可,
但是若两种动画时长不一样时会出现诡异的效果,animate.css为1s,过渡动画为0.5s
可通过type属性进行确定以哪种动画市场为准,一般时间以长的为准(可选animation或transition)
也可使用绑定duration属性来自定义决定动画时长,该值可以是一个数字(单位毫秒),也可是一个对象
</h2>
<transition
type="animation"
enter-active-class="animate__animated animate__backInDown v-enter-active"
leave-active-class="animate__animated animate__backOutDown v-leave-active">
<h1 v-show="show">type属性确定动画时长</h1>
</transition>
<transition
:duration="1000"
enter-active-class="animate__animated animate__backInDown v-enter-active"
leave-active-class="animate__animated animate__backOutDown v-leave-active">
<h1 v-show="show">绑定duration属性确定动画时长(数值方式)入场和出场</h1>
</transition>
<transition
:duration="{enter:3000,leave:2000}"
enter-active-class="animate__animated animate__backInDown v-enter-active"
leave-active-class="animate__animated animate__backOutDown v-leave-active">
<h1 v-show="show">绑定duration属性确定动画时长(对象方式)分别定义入场和出场</h1>
</transition>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app",
data(){ return { show: true } },
methods: { clickHandle(){ this.show = !this.show } }
});
</script>
</body>
</html>
JS动画
自定义JS动画
transition
标签在入场和出场时会自动向外触发事件,外部可通过对这些事件的监听来执行对应的回调
事件名 | 描述 | 回调 | 描述 |
---|---|---|---|
before-enter |
入场动画开始前 | callback(el) |
el 是要执行动画的DON元素 |
enter |
入场动画 | callback(el,done) |
el 是要执行动画的DON元素,done 是用来告诉Vue动画结束的回调函数 |
after-enter |
入场动画结束 | callback(el) |
el 是要执行动画的DON元素 |
leave-enter |
出场动画开始前 | callback(el) |
el 是要执行动画的DON元素 |
leave |
出场动画 | callback(el,done) |
el 是要执行动画的DON元素,done 是用来告诉Vue动画结束的回调函数 |
leave-enter |
出场动画结束 | callback(el) |
el 是要执行动画的DON元素 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<button @click="clickHandle">按钮</button>
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
>
<h1 v-show="show">JS动画</h1>
</transition>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app",
data(){ return { show: true } },
methods: {
clickHandle(){ this.show = !this.show },
beforeEnter(el){ console.log("beforeEnter"); },
enter(el,done){ console.log("enter"); done() }, //若不调用done()方法,则afterEnter不会执行,因为Vue不知道何时动画结束
afterEnter(el){ console.log("afterEnter"); },
beforeLeave(el){ console.log("beforeLeave"); },
leave(el,done){ console.log("leave"); done() }, //若不调用done()方法,则afterLeave不会执行,因为Vue不知道何时动画结束
afterLeave(el){ console.log("afterLeave"); },
}
});
</script>
</body>
</html>
velocity.js
在enter
和leave
事件绑定函数中使用velocity.js对元素做动画即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
</head>
<body>
<div id="app">
<button @click="clickHandle">按钮</button>
<transition
@enter="enter"
@leave="leave"
>
<h1 v-show="show">JS动画</h1>
</transition>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app",
data(){ return { show: true } },
methods: {
clickHandle(){ this.show = !this.show },
enter(el, done){
Velocity(el, { opacity: 1 }, { duration: 1000, complete: done });
// Velocity.js会再结束时自动执行done()函数
},
leave(el, done){
Velocity(el, { opacity: 0 }, { duration: 1000, complete: done });
// Velocity.js会再结束时自动执行done()函数
}
}
});
</script>
</body>
</html>
多元素/组件动画
多元素切换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
<style>
.v-enter,
.v-leave-to{
opacity: 0;
}
.v-enter-active,
.v-leave-active{
transition: all 1s;
}
</style>
</head>
<body>
<div id="app">
<h2>
transition组件中只能有一个DOM元素,若有多个元素则必须使用v-if或动态组件显示一个,v-show却不行<br>
Vue的v-if、v-else-if和v-else会经可能的复用DOM,所以不会有动画效果,可以为DOM增加一个key值得以解决<br>
可以为transition增加一个mode属性,该属性值可选 in-out 和 out-in 两种效果
</h2>
<button @click="clickHandle">按钮</button>
<transition mode="in-out">
<h1 v-if="show" key="one">one</h1>
<h1 v-else key="two">two</h1>
</transition>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app",
data(){ return { show: true } },
methods: { clickHandle(){ this.show = !this.show } }
});
</script>
</body>
</html>
列表动画
对列表渲染的元素进行动画,使用transition-group
包裹列表元素即可,用法与transition
一致,该标签的实质是为每一个列表项添加一个transition
标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
<style>
.v-enter,
.v-leave-to{
opacity: 0;
}
.v-enter-active,
.v-leave-active{
transition: all 1s;
}
</style>
</head>
<body>
<div id="app">
<button @click="pushHandle">push</button>
<button @click="popHandle">pop</button>
<ul>
<transition-group>
<li v-for="item in array" :key="item">{{item}}</li>
</transition-group>
</ul>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app",
data(){ return { array: [] } },
methods: {
pushHandle(){ this.array.push(this.array.length) },
popHandle(){ this.array.pop() }
}
});
</script>
</body>
</html>
Comments NOTHING