前提条件:
在显示Vue封装的效果之前,首先我们演示一下,在不经过Vue实例的动画效果,即使用CSS样式进行动画的制作
演示效果:
代码实现:
<template>
<div>
<button type="button" @click="show = !show">动画</button>
<!-- 在这里将应用什么样的样式手动的使用类名绑定在DOM上,实现某一种特定的样式-->
<h1 v-show="show" class="com">你好世界</h1>
</div>
</template>
<script>
export default {
name: "animation_demo",
data(){
return {
show:true
}
}
}
</script>
<style scoped>
h1{
background-color: orange;
}
/*动画效果的类名*/
.com{
/*表示执行的动画效果,后面的属性表示动画将在1S内完成*/
animation: translate 1s;
}
.go{
/*表示执行的动画效果,后面的属性表示动画将在一秒内完成,并且反转动画的效果*/
animation: translate 1s reverse;
}
/*使用@keyframes来创建一个动画,后面跟着的字符串就是动画的名字,from表示开始,to表示结束*/
/*这是一个简单的动画,*/
@keyframes translate {
from{
/*CSS transform 属性允许你旋转,缩放,倾斜或平移给定元素。*/
/*其中translateX就表示按X轴,也就是横向的平移这个元素,平移百分之一百也就是完全的向左移除屏幕*/
/*如果是正数则表示向右移除*/
transform: translateX(-100%);
}
to{
/*表示动画结束时的样式,动画结束时,平移百分之0也就是恢复原位,整体的动画效果表示为从屏幕左边逐渐平移到屏幕中间*/
transform: translateX(0);
}
}
</style>
可以看到,在不使用Vue封装的动画的前提下,也是可以实现动画效果的,只不过需要使用回调方法进行不同动画类的切换,比较的麻烦,所以Vue封装了一个可以来回切换的动画效果
Vue对动画进行的封装:
在使用Vue进行动画封装的时候,首先需要对要进行动画的DOM使用transition标签进行包裹,并且不再手动的使用class指定动画的对象,而由Vue在合适的时候调用合适的动画,那么Vue怎么知道在何时调用什么样式呢?这里就需要对动画类的名字进行说明了,在之前,我们给动画执行类的名字设定的是com和go,但是在Vue中,如果你想让它智能的选择使用何种动画,就需要使用Vue认识的名字,写作:v-enter-active,表示进入的动画。v-leave-active,表示退出的动画
演示效果:
代码实现:
<template>
<div>
<button type="button" @click="show = !show">动画</button>
<transition>
<!-- 之前使用什么样的动画样式需要手动的更改,现在则由Vue帮我们选择,所以这里就不需要写class属性了-->
<h1 v-show="show">你好世界</h1>
</transition>
</div>
</template>
<script>
export default {
name: "animation_demo",
data(){
return {
show:true
}
}
}
</script>
<style scoped>
h1{
background-color: orange;
}
/*动画效果的类名,之前是随意的设定,现在需要修改为Vue可以只能识别的类名*/
.v-enter-active{
/*表示执行的动画效果,后面的属性表示动画将在1S内完成*/
animation: translate 1s;
}
.v-leave-active{
/*表示执行的动画效果,后面的属性表示动画将在一秒内完成,并且反转动画的效果*/
animation: translate 1s reverse;
}
/*使用@keyframes来创建一个动画,后面跟着的字符串就是动画的名字,from表示开始,to表示结束*/
/*这是一个简单的动画,*/
@keyframes translate {
from{
/*CSS transform 属性允许你旋转,缩放,倾斜或平移给定元素。*/
/*其中translateX就表示按X轴,也就是横向的平移这个元素,平移百分之一百也就是完全的向左移除屏幕*/
/*如果是正数则表示向右移除*/
transform: translateX(-100%);
}
to{
/*表示动画结束时的样式,动画结束时,平移百分之0也就是恢复原位,整体的动画效果表示为从屏幕左边逐渐平移到屏幕中间*/
transform: translateX(0);
}
}
</style>
这里有一个小的注意点就是动画播放的时机,实际上,在我们点击按钮,使show的值变成false,DOM对象消失之前,他会执行退出的动画,而再次点击按钮,使show的值变成true,在DOM对象出现之前,他会执行出现的动画,也就是说,是先改变的值,再执行动画,最后DOM对象完整的出现在页面中。
四个小细节:
transition并不会被渲染成标签:
在我们使用transition标签的时候,在浏览器打开检查页面,可以看到在h1标签也就是我们的绑定动画样式的标签并没有被标签包裹:
说明Vue在最终解析的时候,并没有将transition标签渲染出来
transition的name属性:
transition可以具有一个name属性,表示这个动画的名字,如果你给一个transition标签添加了一个name属性,那么在使用类名的时候,就不能写v-enter-active了,需要改成:name属性值-enter-active,因为v是当没有name属性时默认使用的,如果由name则需要进行对应的修改
例如:这里添加了一个name属性
那么,在使用样式的类名的时候,就需要修改成:
其实name属性存在的意义更多的是在于,当页面中存在多个需要不同动画的元素时,使用name属性可以精准的给每一个元素添加对应的属性
appear属性:
在我们刷新页面的时候可以发现,在页面第一次被加载出来的时候,元素是没有进场动画的,如果想让元素在第一次加载页面的时候就出现动画,需要在transition标签上加入一个appear属性:
这样就可以在第一次加载页面的时候也出现动画了
动画的实现并不是Vue所关心的:
在上图中,是由具体实现动画的类去实现动画,而Vue在意的只是识别相应的实现动画的类的类名,而动画的实现并不是Vue的操作范围,说明Vue不跟动画进行对话,而是跟样式的类名进行对话。
Vue对过渡进行的封装:
在上个案例中,我们看到了Vue对于动画的封装,而现在,我们开始看Vue对于过渡效果的封装,我们分为三个阶段开始慢慢的深入:
第一阶段:
在之前的动画的案例中,我们是定义了一个动画效果,并在合适的时候使用了这个效果,但是我们现在要使用过渡,所以定义动画和使用动画的过程就不再需要了,取而代之的是两个新的类:tran-enter,进入的起点和tran-enter-to,进入的终点,根据这两个类的描述可以得知,这两个类是定义过渡开始的关键帧的,也就是开始的位置和结束的位置,所以我们在这两个类中定义过渡开始的起点和终点,但是只有关键帧是不够用的,还需要定义动画的持续时间和运动效果,那么现在没有active了,就遵循,给谁用过渡,就在谁那里定义效果。所以,在本案例中是给h1标签使用过渡,就在h1标签中定义了过渡动画。具体的效果如下:
代码实现:
<template>
<div>
<button type="button" @click="show = !show">动画</button>
<transition name="tran" appear>
<h1 v-show="show">你好世界</h1>
</transition>
</div>
</template>
<script>
export default {
name: "animation_demo",
data(){
return {
show:true
}
}
}
</script>
<style scoped>
h1{
background-color: orange;
transition: 1s linear;
}
/*进入的起点*/
.tran-enter{
transform: translateX(-100%);
}
/*进入的终点*/
.tran-enter-to{
transform: translateX(0);
}
</style>
第二阶段:
在效果图中可以看到,进入时的效果体现出来了,但是退出时的效果则是在等待了一秒后直接消失,并没有显示出移走的效果,所以就需要用到我们的另外两个类来达成离开时候的效果:tran-leave,离开时的起点和rean-leave-to,离开时的终点,在添加对应的类之后,效果如下:
代码实现:
<template>
<div>
<button type="button" @click="show = !show">动画</button>
<transition name="tran" appear>
<h1 v-show="show">你好世界</h1>
</transition>
</div>
</template>
<script>
export default {
name: "animation_demo",
data(){
return {
show:true
}
}
}
</script>
<style scoped>
h1{
background-color: orange;
transition: 1s linear;
}
/*进入的起点*/
.tran-enter{
transform: translateX(-100%);
}
/*进入的终点*/
.tran-enter-to{
transform: translateX(0);
}
/*离开的起点*/
.tran-leave{
transform: translateX(0);
}
/*离开的终点*/
.tran-leave-to{
transform: translateX(100%);
}
</style>
第三阶段:最后一个阶段主要是对代码的优化部分
在第二阶段的时候,可以看到基本的效果已经出现了,但是CSS代码的部分过于冗长,完全没有体现出Vue封装代码的精减性,所以我们可以尝试精简一下代码,可以发现,在CSS代码的部分,进入的起点,就等于离开的终点;而进入的终点,就等于离开的起点。这是一个循环,既然知道这些类的内容都是一样的,那么就可以将这些类写成一个。并且在应用过渡的时候,我们一开始说,谁用过渡就给谁添加过渡,但是之前的做法容易混淆元素样式和过渡动画,所以我们推荐将过渡的效果单独写进一个类选择器中,那么这个类选择器就是我们之前用过的两个active,那么整理整合之后的代码如下:
<template>
<div>
<button type="button" @click="show = !show">动画</button>
<transition name="tran" appear>
<h1 v-show="show">你好世界</h1>
</transition>
</div>
</template>
<script>
export default {
name: "animation_demo",
data(){
return {
show:true
}
}
}
</script>
<style scoped>
h1{
background-color: orange;
}
/*进入的起点,离开的终点*/
.tran-enter,.tran-leave-to{
transform: translateX(-100%);
}
/*进入的终点,离开的起点*/
.tran-enter-to,.tran-leave{
transform: translateX(0);
}
/*将过渡动画从元素样式中分离出来,单独写成一个类*/
.tran-enter-active,.tran-leave-active{
transition: 1s linear;
}
</style>
小细节:
在我按下按钮启动动画的时候,在控制台查看源代码的时候,你会发现在h1标签,也就是我应用过渡的元素,出现了两个样式:
分别是:.tran-leave-active和.tran-leave-to,而我们再次点击的时候,只会出现.tran-enter-active和.tran-enter-to两个类,但是我们在定义的时候,一共定义了六个类,这里只看到了两个,还有两个类为什么没有看到?
其实在过渡的过程中,.tran-enter和.tran-leave这两个类,只是定义动画开始的一瞬间的状态,在过度开始的瞬间这两个类就在被应用一帧之后就被删除了,这一瞬间我们是无法看见的,但是看不见不代表没有,如果你不写,那妥妥的报错。
多个元素的过渡:
当我们在使用transition标签的时候,内部只能有一个标签,也就是说一个transition标签只能有一个应用了过渡样式的标签,而在有些时候,我们需要给多个标签添加样式,这时候就需要使用一个新的标签:transition-group,来包裹多个过渡。并且需要给每一个标签添加一个唯一的key值,演示效果如下:
代码实现:
<template>
<div>
<button type="button" @click="show = !show">动画</button>
<!-- 使用一个新的标签将多个过渡动画标签包裹起来-->
<transition-group name="tran" appear>
<!-- 并且给每一个标签添加一个唯一的key值-->
<h1 v-show="show" key="1">你好世界</h1>
<h1 v-show="show" key="2">你好世界</h1>
</transition-group>
</div>
</template>
<script>
export default {
name: "animation_demo",
data(){
return {
show:true
}
}
}
</script>
<style scoped>
h1{
background-color: orange;
}
/*进入的起点,离开的终点*/
.tran-enter,.tran-leave-to{
transform: translateX(-100%);
}
/*进入的终点,离开的起点*/
.tran-enter-to,.tran-leave{
transform: translateX(0);
}
/*将过渡动画从元素样式中分离出来,单独写成一个类*/
.tran-enter-active,.tran-leave-active{
transition: 1s linear;
}
</style>
这种场景主要应用于当我们给列表应用动画的时候,比如ul或ol列表标签,或许有人会认为,既然transition标签只能包裹一个标签,那么将多个标签封装在一个div标签内不也能实现效果吗?但是如果我们有一个新的需求,即两个标签需要应用不同的样式,这时候,包裹成一个div的做法就没有那么灵活了,比如下面的展示效果:
代码实现:
<template>
<div>
<button type="button" @click="show = !show">动画</button>
<!-- 使用一个新的标签将多个过渡动画标签包裹起来-->
<transition-group name="tran" appear>
<!-- 在上一个案例的基础上,对内容显示的变量进行取反,就可以显示交错显示的效果-->
<h1 v-show="!show" key="1">你好世界</h1>
<h1 v-show="show" key="2">你好世界</h1>
</transition-group>
</div>
</template>
<script>
export default {
name: "animation_demo",
data(){
return {
show:true
}
}
}
</script>
<style scoped>
h1{
background-color: orange;
}
/*进入的起点,离开的终点*/
.tran-enter,.tran-leave-to{
transform: translateX(-100%);
}
/*进入的终点,离开的起点*/
.tran-enter-to,.tran-leave{
transform: translateX(0);
}
/*将过渡动画从元素样式中分离出来,单独写成一个类*/
.tran-enter-active,.tran-leave-active{
transition: 1s linear;
}
</style>
集成第三方动画:以Animate为案例
首先我们来到npm网站查看这个库如何使用:
动画 - npm (npmjs.com)
我们还可以查看这个动画库的官网,在他的官网中明确写明了如何使用以及查看样式:
动画.css |CSS动画的跨浏览器库。 (animate.style)
这些基本使用和进阶使用都在官网中有明确的介绍,那么具体的使用可以按照下面的流程:
首先可以下载,也可以使用CDN引入,然后将transition的name属性修改为:
animate__animated animate__bounce
然后添加两个新的属性:enter-active-class和leave-active-class用来定义进入的动画和离开的动画,就不再需要让我们自己定义和修改了,展示效果如下:
代码实现:
<template>
<div>
<button type="button" @click="show = !show">动画</button>
<transition-group
appear
name="animate__animated animate__bounce"
enter-active-class="animate__rubberBand"
leave-active-class="animate__hinge"
>
<h1 v-show="show" key="2">你好世界</h1>
</transition-group>
</div>
</template>
<script>
export default {
name: "animation_demo",
data(){
return {
show:true
}
}
}
</script>
<style scoped>
h1{
background-color: orange;
}
</style>
这里只是展示了两个基本的效果,他还有很多的好看的效果,各位可以尝试多多使用。值得注意的是,在我们使用不同的引入方式的时候,CDN的方式,需要放在HTML页面中,import导入的方式,需要放置在组件中,一定要分辨这两个的关系。
课本上的简单案例:
<template>
<div>
<button type="button" @click="show = !show">点击切换效果</button>
<transition name="fade">
<p v-show="show">你好世界</p>
</transition>
</div>
</template>
<script>
export default {
name: "transitionDemo",
data(){
return {
show:true
}
},
}
</script>
<style scoped>
/*当动画进入的时候的状态 离开过渡的时候的状态*/
.fade-enter,.fade-leave-to{
opacity:0
}
/*动画进入时的样式和动画离开时的样式*/
.fade-enter-active,.fade-leave-active{
transition: opacity .5s;
}
</style>
<!--
简单的介绍:
过渡是指在图像消失和出现的时候进行的平滑过渡特效
在本案例中,图像的消失和出现是由v-show的值来决定的,当我们按下按钮的时候,原本为true的值变成了false,原本应该被显示的图像消失了
但是在消失之前,会先播放实现设定好的动画,在本案例中的动画的体现就是透明度的变化。
在消失的时候从不透明到完全透明,在出现的时候从完全透明到不透明的过渡。
因为动画开始和结束时的状态是一样的,所以.fade-enter,.fade-leave-to这两个类可以写在一起
而且动画进入和离开的样式是一样的,所以.fade-enter-active,.fade-leave-active这两个类可以写在一起
-->
展示效果:
案例二
<template>
<div>
<button @click="show = !show">点击淡出</button>
<transition name="fade">
<img src="../assets/logo.png" alt="logo" v-show="show">
</transition>
</div>
</template>
<script>
export default {
name: "fadesOut",
data(){
return {
show:true
}
}
}
</script>
<style scoped>
.fade-enter{
width: 100px;
height: 100px;
opacity: 0;
}
/*离开过渡的时候的样式*/
/*如果将值改为300,则不会缩小,只会淡化*/
.fade-leave-active{
opacity: 0;
width: 100px;
height: 100px;
}
.fade-enter-active{
opacity: 1;
width: 300px;
height: 300px;
}
.fade-enter-active,.fade-leave-active{
transition: 1s all ease;
}
img{
width: 300px;
height: 300px;
}
</style>
展示效果: