Vue3中實現(xiàn)過渡動畫的方法小結(jié)
前言
首先拋開 vue 本身,假設(shè)需要給某個 Dom 元素實現(xiàn)一些過渡動畫,那么下面這些事是必須的:
- 實現(xiàn)目標(biāo)元素不同時刻下的樣式,常見做法就是抽取在不同的 css 選擇器中
- 根據(jù)不同時刻切換不同的 css 選擇器以達(dá)到樣式的變化
- 設(shè)置樣式過度的方式和時間,如:transition: all .5s ease
而在 vue 中實現(xiàn)過渡動畫,那就不得不提到其內(nèi)置的 transition 組件,而 transition 組件幫我們實現(xiàn)了第一件事,就是對組件不同時刻設(shè)置不同的 css 選擇器,甚至于可以對這個選擇器進(jìn)行自定義,因此,我們只需要完成后面兩件事即可,當(dāng)然這里對 transition 組件的用法就不過多進(jìn)行介紹.
當(dāng)然這里的實現(xiàn)動畫的方式,會從下面幾個方面來實現(xiàn):
CSS3 transition屬性CSS3 @keyframes幀動畫- 第三方庫
animate.css - 第三方庫
gsap —— GreenSock Animation Platform,在官方文檔中有提及的

<transition> 組件 + CSS3 transition 屬性
話不多說,直接來實現(xiàn)一個簡單的 顯示/隱藏 的過渡動畫:
- 顯示時:從左側(cè)滑入,且透明度增大
- 隱藏時:從右側(cè)滑出,且透明度減小

// toggle.vue
<script setup lang="ts">
import { ref } from 'vue'
const isShow = ref(true)
const toggle = () => {
isShow.value = !isShow.value
}
</script>
<template>
<transition name="fade">
<h1 v-if="isShow">this is h1 content!</h1>
</transition>
<div>
<button @click="toggle">toggle</button>
</div>
</template>
<style>
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.fade-enter-from {
transform: translateX(-30px);
}
.fade-enter-to ,
.fade-leave-to {
transform: translateX(30px);
}
.fade-enter-to,
.fade-leave-from {
opacity: 1;
}
.fade-enter-active,
.fade-leave-active {
transition: all .5s ease;
}
h1 {
width: 300px;
margin: 10px auto;
}
</style>
<transition> 組件 + CSS3 @keyframes 幀動畫
css 中除了使用 transition 屬性實現(xiàn)不同樣式間的過渡,也可以直接使用 @keyframes 來實現(xiàn)幀動畫.

// hang.vue
<script setup lang="ts">
import { ref } from 'vue'
const isShow = ref(true)
const hang = () => {
isShow.value = !isShow.value
}
</script>
<template>
<transition name="fade">
<h1 v-if="isShow">this is h1 content!</h1>
</transition>
<div>
<button @click="hang">trigger</button>
</div>
</template>
<style>
.fade-enter-active {
animation: hang 0.5s 1 ease;
}
.fade-leave-active {
animation: hang 0.5s 1 ease reverse;
}
@keyframes hang {
0% {
transform: translateY(30px) rotateZ(30deg);
opacity: 0;
}
25% {
transform: translateY(24px) rotateZ(24deg);
opacity: 0.3;
}
50% {
transform: translateY(18px) rotateZ(18deg);
opacity: 0.6;
}
75% {
transform: translateY(12px) rotateZ(12deg);
opacity: 0.8;
}
100% {
transform: translateY(-5px) rotateZ(0deg);
opacity: 1;
}
}
h1 {
width: 300px;
margin: 10px auto;
}
</style>
<transition> 組件 + 第三方庫 animate.css
直接使用 animate.css 中對應(yīng)效果的動畫名,配合 animation 屬性進(jìn)行使用即可.
對應(yīng)的效果和動畫名可通過 animat.style 效果預(yù)覽 查看

// animate.vue
<script setup lang="ts">
import { ref } from 'vue'
import './animate.css'
const isShow = ref(true)
const hang = () => {
isShow.value = !isShow.value
}
</script>
<template>
<transition name="fade">
<h1 v-if="isShow">this is h1 content!</h1>
</transition>
<div>
<button @click="hang">trigger</button>
</div>
</template>
<style>
.fade-enter-active {
animation: flip 0.5s 1 ease;
}
.fade-leave-active {
animation: flip 0.5s 1 ease reverse;
}
h1 {
width: 300px;
margin: 10px auto;
}
</style>
<transition> 組件 + 第三方庫 gsap
通過上面幾個簡單的動畫例子,其實不難發(fā)現(xiàn),無論是自己實現(xiàn)動畫,還是使用已有的 css 樣式庫都有一個缺點,就是不夠靈活,比如:某些 css 屬性值只能是一個不變的值
如果有些場景需要一些更復(fù)雜和靈活的 css 樣式,那么顯然前面提到的方式并不符合實際需求,換句話說,如果需要在 js 中實現(xiàn)樣式的過渡,以及設(shè)置動態(tài)的 css 樣式屬性值時,就有必要使用一些第三方庫,如:gsap,幫助我們更方便的實現(xiàn)需求.

// gsap.vue
<script setup>
import { ref } from "vue";
import gsap from "gsap";
let timeScaleTween = null;
const enter = (el) => {
const tl = gsap.timeline(),
atom = el,
dur = 2,
del = 0.5;
tl.fromTo(
".electron",
{ rotationX: 90 },
{
rotationZ: -360,
rotationX: 90,
ease: "none",
duration: dur,
stagger: {
each: -del,
repeat: -1,
},
},
0
);
tl.to(
".path",
{
rotationZ: 360,
ease: "none",
duration: dur,
stagger: {
each: -del,
repeat: -1,
},
},
0
);
// Add a rotation to the whole atom
gsap.set(atom, { transformOrigin: "center center" });
gsap.to(atom, { rotation: 360, ease: "none", repeat: -1, duration: 300 });
// Skip the loading
tl.progress(0.9999);
timeScaleTween = gsap.to(tl, {
duration: 0.75,
timeScale: 0.1,
paused: true,
});
};
const slow = () => {
timeScaleTween.play()
}
const reverse = () => {
timeScaleTween.reverse()
}
const isShow = ref(false);
const show = () => {
isShow.value = true
};
</script>
<template>
<transition name="fade" @enter="enter">
<div class="atom" v-if="isShow">
<div class="orbit">
<div class="path">
<div class="electron"></div>
</div>
</div>
<div class="orbit">
<div class="path">
<div class="electron"></div>
</div>
</div>
<div class="orbit">
<div class="path">
<div class="electron"></div>
</div>
</div>
<div class="orbit">
<div class="path">
<div class="electron"></div>
</div>
</div>
<div class="nucleus"></div>
</div>
</transition>
<div>
<button @click="show">show</button>
<button @click="slow">slow</button>
<button @click="reverse">reverse</button>
</div>
</template>
<style>
@import url("https://fonts.googleapis.com/css?family=Signika+Negative:300,400&display=swap");
body {
font-family: "Signika Negative", sans-serif;
font-weight: 300;
background: grey;
overflow: hidden;
color: white;
text-align: center;
}
.atom {
position: absolute;
top: 50%;
left: 50%;
width: 300px;
height: 300px;
perspective: 1000;
margin-left: -170px;
margin-top: -146px;
transform-style: preserve-3d;
}
.nucleus {
position: absolute;
top: 50%;
left: 50%;
margin: -10px 0 0 -10px;
width: 25px;
height: 25px;
border-radius: 50%;
background: #272727;
}
.orbit {
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 300px;
border-radius: 300px;
border: 5px solid #ccc;
transform-style: preserve-3d;
transform: rotateX(80deg) rotateY(20deg);
}
.orbit:nth-child(2) {
transform: rotateX(80deg) rotateY(70deg);
}
.orbit:nth-child(3) {
transform: rotateX(80deg) rotateY(-20deg);
}
.orbit:nth-child(4) {
transform: rotateX(80deg) rotateY(-50deg);
}
.path {
width: 300px;
height: 300px;
position: relative;
transform-style: preserve-3d;
}
.electron {
position: absolute;
top: -5px;
left: 50%;
margin-left: -5px;
width: 10px;
height: 10px;
border-radius: 10px;
background: #ccc;
}
button{
margin: 10px;
}
</style>
本文通過四種方式實現(xiàn)了一些簡單動畫,但其實在 vue 中實現(xiàn)動畫也不一定要使用 transition 組件,具體場景還是得具體分析.
以上就是Vue3中實現(xiàn)過渡動畫的方法小結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Vue3過渡動畫的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue 使用axios 數(shù)據(jù)請求第三方插件的使用教程詳解
這篇文章主要介紹了vue 使用axios 數(shù)據(jù)請求第三方插件的使用 ,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-07-07
vue+springboot實現(xiàn)項目的CORS跨域請求
這篇文章主要介紹了vue+springboot實現(xiàn)項目的CORS跨域請求,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-09-09
vuex中store存儲store.commit和store.dispatch的用法
這篇文章主要介紹了vuex中store存儲store.commit和store.dispatch的用法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
vue?如何刪除數(shù)組中的某一條數(shù)據(jù)
這篇文章主要介紹了vue?如何刪除數(shù)組中的某一條數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
Vue3中ref數(shù)組的監(jiān)聽實現(xiàn)方式
Vue3中監(jiān)聽ref定義的數(shù)組,需根據(jù)監(jiān)聽需求選擇合適的監(jiān)聽方法,對于空數(shù)組,推薦使用深度監(jiān)聽來捕捉數(shù)組內(nèi)部變化,同時,確保修改數(shù)組的方式是響應(yīng)式的,以保證監(jiān)聽器能正常工作,根據(jù)具體需求,可以選擇直接深度監(jiān)聽、監(jiān)聽數(shù)組長度變化或提取屬性監(jiān)聽等方案2025-10-10
element-ui中select下拉框加載大數(shù)據(jù)渲染優(yōu)化方式
這篇文章主要介紹了element-ui中select下拉框加載大數(shù)據(jù)渲染優(yōu)化方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11

