写在前面
在实际开发中,为了增加用户体验,经常会使用到过渡动画,而过渡动画在CSS中是通过transition和animation实现的。而在Vue中,Vue本身中内置了一些组件和API可以帮助我们方便的实现过渡动画效果。
备注: 所谓过渡动画,简而言之就是从一种状态变成另一种状态的过程;所以不管是vue动画还是js动画都是需要触发条件的,触发条件就是在哪种情况下会触发一种状态到另外一种状态的变化;比如(v-if、v-show、:hover、:active、或者click点击等等~)
一、vue过渡
vue中提供transition组件为元素自动添加进入/离开的过渡效果
在线demo编写: stackblitz.com/edit/vitejs…
1. transition组件j基本使用
<template>
<div class="box">
<button class="btn" @click="btnClick">click</button>
<transition>
<img
v-if="isShow"
src="./assets/vue.svg"
class="logo vue"
alt="Vue logo"
/>
</transition>
</div>
</template>
<script setup>
import { ref } from 'vue';
const isShow = ref(false);
const btnClick = () => {
isShow.value = !isShow.value;
};
</script>
<style scoped>
.box {
display: flex;
flex-direction: column;
}
.btn {
margin-bottom: 50px;
}
.logo {
width: 100px;
height: 100px;
}
/* 进入之前和离开后的样式 */
.v-enter-from,
.v-leave-to {
opacity: 0;
}
/* 离开和进入过程中的样式 */
.v-enter-active,
.v-leave-active {
/* 添加过渡动画 */
transition: opacity 8s ease;
}
/* 进入之后和离开之前的样式 */
.v-enter-to,
.v-leave-from {
opacity: 1;
}
</style>
2. transition组件的class命名规则
transition组件的class命名规则默认前缀是v-, 如果给transition设置了name属性,比如设置name="test",则class命名的规则的前缀就变成test-。
(v-enter-from变成test-enter-from)
<template>
<div class="box">
<button class="btn" @click="btnClick">click</button>
<transition name="test">
<img
v-if="isShow"
src="./assets/vue.svg"
class="logo vue"
alt="Vue logo"
/>
</transition>
</div>
<!-- <HelloWorld msg="Vite + Vue" /> -->
</template>
<script setup>
import { ref } from 'vue';
const isShow = ref(false);
const btnClick = () => {
isShow.value = !isShow.value;
};
</script>
<style scoped>
.box {
display: flex;
flex-direction: column;
}
.btn {
margin-bottom: 50px;
}
.logo {
width: 100px;
height: 100px;
}
/* 进入之前和离开后的样式 */
.test-enter-from,
.test-leave-to {
opacity: 0;
}
/* 离开和进入过程中的样式 */
.test-enter-active,
.test-leave-active {
/* 添加过渡动画 */
transition: opacity 8s ease;
}
/* 进入之后和离开之前的样式 */
.test-enter-to,
.test-leave-from {
opacity: 1;
}
</style>
1.3 过渡的阶段
二、js过渡和动画
1. transition过渡
1.1 transition语法
transition: 过渡属性 过渡时间 过渡动画函数 过渡延迟
// 需要多个属性过渡时用逗号隔开
transition: 过渡属性1 过渡时间1 过渡动画函数1 过渡延迟1, 过渡属性2 过渡时间2 过渡动画函数2 过渡延迟2
// 需要所有属性都过渡, 则过渡属性是all
transition: all 过渡时间 过渡动画函数 过渡延迟
过渡动画函数:transition的状态变化速度(又称timing function),默认不是匀速的,而是逐渐放慢,这叫做ease。
`
除了ease以外,其他模式还包括
(1)linear:匀速
(2)ease-in:加速
(3)ease-out:减速
(4)cubic-bezier函数:自定义速度模式
最后那个cubic-bezier,可以使用工具网站来定制。
img{
transition: 1s height cubic-bezier(.83,.97,.05,1.44);
}
上面的代码会产生一个最后阶段放大过度、然后回缩的效果。
1.2 transition实战
可以在菜鸟平台上练习:www.runoob.com/try/try.php…
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
div
{
width:100px;
height:100px;
background:red;
transition:width 4s;
// transition:width 4s ease, transform 4s; 指定多个过渡属性时逗号隔开
}
div:hover
{
width:300px;
transform: translateY(-4px);
}
</style>
</head>
<body>
<div></div>
<p>鼠标移动到 div 元素上,查看过渡效果。</p>
</body>
</html>
鼠标放到div上之后,相当于触发了hover,此时宽度会从100px慢慢经过4s的过程,慢慢增长到300px,同时div还会在y轴上面上移4px;当鼠标从div上脱离之后,会自动从hover状态慢慢经过4s过渡到原始状态(也就是宽度从300px慢慢递减到100px,transform同理)
1.3 transition注意点
注意点:
(1)目前,各大浏览器(包括IE 10)都已经支持无前缀的transition,所以transition已经可以很安全地不加浏览器前缀。
(2)不是所有的CSS属性都支持transition,完整的列表查看这里,以及具体的效果。
(3)transition需要明确知道,开始状态和结束状态的具体数值,才能计算出中间状态。比如,height从0px变化到100px,transition可以算出中间状态。但是,transition没法算出0px到auto的中间状态,也就是说,如果开始或结束的设置是height: auto,那么就不会产生动画效果。类似的情况还有,display: none到block,background: url(foo.jpg)到url(bar.jpg)等等。
局限性:
transition的优点在于简单易用,但是它有几个很大的局限。
(1)transition需要事件触发,所以没法在网页加载时自动发生。
(2)transition是一次性的,不能重复发生,除非一再触发。
(3)transition只能定义开始状态和结束状态,不能定义中间状态,也就是说只有两个状态。
(4)一条transition规则,只能定义一个属性的变化,不能涉及多个属性。
CSS Animation就是为了解决这些问题而提出的。
2. 动画
完整demo:www.runoob.com/try/try.php…
动画和过渡有什么区别呢?个人感觉是过渡定义的是从开始状态到结束状态变化的过程;而动画是除了定义开始状态到结束状态变化的过程,并且可以将这个过程拆分成不同的阶段,可以定义每个阶段是什么状态,比如从开始状态变化到50%的时候,可以定义50%那刻的状态。
2.1 基本使用
首先,CSS Animation需要指定动画一个周期持续的时间,以及动画效果的名称
div:hover {
animation: 1s rainbow;
}
上面代码表示,当鼠标悬停在div元素上时,会产生名为rainbow的动画效果,持续时间为1秒。为此,我们还需要用keyframes关键字,定义rainbow效果
@keyframes rainbow {
0% { background: blue; }
50% { background: black; }
100% { background: yellowgreen; }
}
上面代码表示,rainbow效果一共有三个状态,分别为起始(0%)、中点(50%)和结束(100%)。如果有需要,完全可以插入更多状态。效果如下(完整代码如下,可自行尝试: www.runoob.com/try/try.php… )。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
div
{
width:100px;
height:100px;
background:red;
}
div:hover
{
animation: 1s rainbow forwards;
}
@keyframes rainbow {
0% { background: blue; }
50% { background: black; }
100% { background: yellowgreen; }
}
</style>
</head>
<body>
<div></div>
</body>
</html>
默认情况下,动画只播放一次。加入infinite关键字,可以让动画无限次播放。
div:hover {
animation: 1s rainbow infinite;
}
也可以指定动画具体播放的次数,比如3次。
div:hover {
animation: 1s rainbow 3;
}
2.2 keyframes的写法
@keyframes rainbow {
0% { background: #c00 }
50% { background: orange }
100% { background: yellowgreen }
}
0%可以用from代表,100%可以用to代表,因此上面的代码等同于下面的形式
@keyframes rainbow {
from { background: #c00 }
50% { background: orange }
to { background: yellowgreen }
}
甚至,可以把多个状态写在一行。
@keyframes pound {
from,to { transform: none; }
50% { transform: scale(1.2); }
}
2.3 相关的属性
2.3.1 animation-fill-mode
动画结束以后,会立即从结束状态跳回到起始状态。如果想让动画保持在结束状态,需要使用animation-fill-mode属性
(1)none:默认值,回到动画没开始时的状态。
(2)backwards:让动画回到第一帧的状态。
(3)forwards: 表示让动画停留在结束状态。
(4)both: 根据animation-direction(见后)轮流应用forwards和backwards规则。
div:hover {
animation: 1s rainbow forwards;
}
2.3.2 animation-direction
动画循环播放时,每次都是从结束状态跳回到起始状态,再开始播放。animation-direction属性,可以改变这种行为。
取值:normal(默认值)、alternate、reverse、alternate-reverse等值
下面看这个例子:
@keyframes rainbow {
0% { background-color: yellow; }
100% { background: blue; }
}
2.4 简写
简写语法如下:
animation: animation-duration animation-delay animation-name animation-timing-function animation-iteration-count animation-fill-mode animation-direction
简写实践如下:
div:hover {
animation: 1s 1s rainbow linear 3 forwards normal;
}
div:hover {
animation-name: rainbow;
animation-duration: 1s;
animation-timing-function: linear;
animation-delay: 1s;
animation-fill-mode:forwards;
animation-direction: normal;
animation-iteration-count: 3;
}