生活随笔
收集整理的這篇文章主要介紹了
Vue3过渡动画实现
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一、認(rèn)識(shí)動(dòng)畫
在開發(fā)中,我們想要給一個(gè)組件的顯示和消失添加某種過(guò)渡動(dòng)畫,可以很好的增加用戶體驗(yàn):
React框架本身并沒(méi)有提供任何動(dòng)畫相關(guān)的API,所以在React中使用過(guò)渡動(dòng)畫我們需要使用一個(gè)第三方庫(kù)react-transition-group; Vue中為我們提供一些內(nèi)置組件和對(duì)應(yīng)的API來(lái)完成動(dòng)畫,利用它們我們可以方便的實(shí)現(xiàn)過(guò)渡動(dòng)畫效果;
我們來(lái)看一個(gè)案例:
Hello World的顯示和隱藏; 通過(guò)下面的代碼實(shí)現(xiàn),是不會(huì)有任何動(dòng)畫效果的;
沒(méi)有動(dòng)畫的情況下,整個(gè)內(nèi)容的顯示和隱藏會(huì)非常的生硬:
如果我們希望給單元素或者組件 實(shí)現(xiàn)過(guò)渡動(dòng)畫,可以使用 transition 內(nèi)置組件 來(lái)完成動(dòng)畫;
二、Vue的transition動(dòng)畫
Vue 提供了 transition 的封裝組件,在下列情形中,可以給任何元素和組件添加進(jìn)入/離開過(guò)渡:
條件渲染 (使用 v-if)條件展示 (使用 v-show) 動(dòng)態(tài)組件 組件根節(jié)點(diǎn)
< template
> < div
> < button @click
= "isShow = !isShow" > 顯示
/ 隱藏
< / button
> < transition name
= "zep" > < h2 v
- if = "isShow" > Hello World
< / h2
> < / transition
> < / div
>
< / template
>
< script
>
export default { name
: "App" , data ( ) { return { isShow
: true } } , methods
: { }
}
< / script
> < style scoped
> . zep
- enter
- from , . zep
- leave
- to
{ opacity
: 0 ; } . zep
- enter
- to
, . zep
- leave
- from { opacity
: 1 ; } . zep
- enter
- active
, . zep
- leave
- active
{ transition
: opacity
2 s ease
; }
< / style
>
三、Transition組件的原理
我們會(huì)發(fā)現(xiàn),Vue自動(dòng)給h2元素添加了動(dòng)畫,這是什么原因呢? 當(dāng)插入或刪除包含在 transition 組件中的元素時(shí),Vue 將會(huì)做以下處理:
1.自動(dòng)嗅探目標(biāo)元素是否應(yīng)用了CSS過(guò)渡或者動(dòng)畫,如果有,那么在恰當(dāng)?shù)臅r(shí)機(jī)添加/刪除 CSS類名; 2.如果 transition 組件提供了JavaScript鉤子函數(shù),這些鉤子函數(shù)將在恰當(dāng)?shù)臅r(shí)機(jī)被調(diào)用; 3.如果沒(méi)有找到JavaScript鉤子并且也沒(méi)有檢測(cè)到CSS過(guò)渡/動(dòng)畫,DOM插入、刪除操作將會(huì)立即執(zhí)行;
那么都會(huì)添加或者刪除哪些class呢?
四、過(guò)渡動(dòng)畫class
我們會(huì)發(fā)現(xiàn)上面提到了很多個(gè)class,事實(shí)上Vue就是幫助我們?cè)谶@些class之間來(lái)回切換完成的動(dòng)畫:
v-enter-from:定義進(jìn)入過(guò)渡的開始狀態(tài)。在元素被插入之前生效,在元素被插入之后的下一幀移除。 v-enter-active:定義進(jìn)入過(guò)渡生效時(shí)的狀態(tài)。在整個(gè)進(jìn)入過(guò)渡的階段中應(yīng)用,在元素被插入之前生效,在過(guò)渡/動(dòng)畫完成之后移除。這個(gè)類可以被用來(lái)定義進(jìn)入過(guò)渡的過(guò)程時(shí)間,延遲和曲線函數(shù)。 v-enter-to:定義進(jìn)入過(guò)渡的結(jié)束狀態(tài)。在元素被插入之后下一幀生效 (與此同時(shí) v-enter-from 被移除),在過(guò)渡/動(dòng)畫完成之后移除。 v-leave-from:定義離開過(guò)渡的開始狀態(tài)。在離開過(guò)渡被觸發(fā)時(shí)立刻生效,下一幀被移除。 v-leave-active:定義離開過(guò)渡生效時(shí)的狀態(tài)。在整個(gè)離開過(guò)渡的階段中應(yīng)用,在離開過(guò)渡被觸發(fā)時(shí)立刻生效,在過(guò)渡/動(dòng)畫完成之后移除。這個(gè)類可以被用來(lái)定義離開過(guò)渡的過(guò)程時(shí)間,延遲和曲線函數(shù)。 v-leave-to:離開過(guò)渡的結(jié)束狀態(tài)。在離開過(guò)渡被觸發(fā)之后下一幀生效 (與此同時(shí) v-leave-from 被刪除),在過(guò)渡/動(dòng)畫完成之后移除。
五、class添加的時(shí)機(jī)和命名規(guī)則
class的name命名規(guī)則如下:
如果我們使用的是一個(gè)沒(méi)有name的transition ,那么所有的class是以 v- 作為默認(rèn)前綴 ; 如果我們添加了一個(gè)name屬性,比如 <transtion name="zep">,那么所有的class會(huì)以 zep- 開頭 ;
六、過(guò)渡css動(dòng)畫
前面我們是通過(guò)transition來(lái)實(shí)現(xiàn)的動(dòng)畫效果,另外我們也可以通過(guò)animation來(lái)實(shí)現(xiàn)。
< template
> < div
class = "app" > < div
> < button @click
= "isShow = !isShow" > 顯示
/ 隱藏
< / button
> < / div
> < transition name
= "zep" > < h2
class = "title" v
- if = "isShow" > Hello World
< / h2
> < / transition
> < / div
>
< / template
>
< script
>
export default { name
: "App" , data ( ) { return { isShow
: true } } , methods
: { }
}
< / script
> < style scoped
> . app
{ width
: 200 px
; margin
: 0 auto
; } . title
{ display
: inline
- block
; } . zep
- enter
- active
{ animation
: bounce
1 s ease
; } . zep
- leave
- active
{ animation
: bounce
1 s ease reverse
; } @keyframes bounce
{ 0 % { transform
: scale ( 0 ) ; } 50 % { transform
: scale ( 1.2 ) ; } 100 % { transform
: scale ( 1 ) ; } }
< / style
>
七、同時(shí)設(shè)置過(guò)渡和動(dòng)畫
Vue為了知道過(guò)渡的完成,內(nèi)部是在監(jiān)聽(tīng) transitionend 或 animationend,到底使用哪一個(gè)取決于元素應(yīng)用的CSS規(guī)則:
如果我們只是使用了其中的一個(gè),那么Vue能自動(dòng)識(shí)別類型并設(shè)置監(jiān)聽(tīng);
但是如果我們同時(shí)使用了過(guò)渡和動(dòng)畫呢?
并且在這個(gè)情況下可能某一個(gè)動(dòng)畫執(zhí)行結(jié)束時(shí),另外一個(gè)動(dòng)畫還沒(méi)有結(jié)束; 在這種情況下,我們可以設(shè)置 type 屬性為 animation 或者 transition 來(lái)明確的告知Vue監(jiān)聽(tīng)的類型;
注意: type值選擇animation還是transition? 誰(shuí)的持續(xù)時(shí)間長(zhǎng)選擇誰(shuí),以確保animation還是transition都能順利執(zhí)行完
< template
> < div
class = "app" > < div
> < button @click
= "isShow = !isShow" > 顯示
/ 隱藏
< / button
> < / div
> < transition name
= "zep" type
= "transition" > < h2
class = "title" v
- if = "isShow" > Hello World
< / h2
> < / transition
> < / div
>
< / template
>
< script
>
export default { name
: "App" , data ( ) { return { isShow
: true } } , methods
: { }
}
< / script
> < style scoped
> . app
{ width
: 200 px
; margin
: 0 auto
; } . title
{ display
: inline
- block
; } . zep
- enter
- from , . zep
- leave
- to
{ opacity
: 0 ; } . zep
- enter
- to
, . zep
- leave
- from { opacity
: 1 ; } . zep
- enter
- active
, . zep
- leave
- active
{ transition
: opacity
2 s ease
; } . zep
- enter
- active
{ animation
: bounce
1 s ease
; } . zep
- leave
- active
{ animation
: bounce
1 s ease reverse
; } @keyframes bounce
{ 0 % { transform
: scale ( 0 ) ; } 50 % { transform
: scale ( 1.2 ) ; } 100 % { transform
: scale ( 1 ) ; } }
< / style
>
八、顯示的指定動(dòng)畫時(shí)間
我們也可以顯示的來(lái)指定過(guò)渡的時(shí)間,通過(guò) duration 屬性。
duration可以設(shè)置兩種類型的值:
number類型:同時(shí)設(shè)置進(jìn)入和離開的過(guò)渡時(shí)間; object類型:分別設(shè)置進(jìn)入和離開的過(guò)渡時(shí)間;
九、過(guò)渡的模式mode
我們來(lái)看當(dāng)前的動(dòng)畫在兩個(gè)元素之間切換的時(shí)候存在的問(wèn)題: 我們會(huì)發(fā)現(xiàn) Hello World 和 你好啊,李銀河是同時(shí)存在的:
這是因?yàn)?strong>默認(rèn)情況下進(jìn)入和離開動(dòng)畫是同時(shí)發(fā)生的; 如果確實(shí)我們希望達(dá)到這個(gè)的效果,那么是沒(méi)有問(wèn)題;
但是如果我們不希望同時(shí)執(zhí)行進(jìn)入和離開動(dòng)畫,那么我們需要設(shè)置transition的過(guò)渡模式:
十、動(dòng)態(tài)組件的切換
上面的示例同樣適用于我們的動(dòng)態(tài)組件:
十一、appear初次渲染
默認(rèn)情況下,首次渲染的時(shí)候是沒(méi)有動(dòng)畫的,如果我們希望給他添加上去動(dòng)畫,那么就可以增加另外一個(gè)屬性appear:
十二、認(rèn)識(shí)animate.css
如果我們手動(dòng)一個(gè)個(gè)來(lái)編寫這些動(dòng)畫,那么效率是比較低的,所以在開發(fā)中我們可能會(huì)引用一些第三方庫(kù)的動(dòng)畫庫(kù), 比如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是一個(gè)已經(jīng)準(zhǔn)備好的、跨平臺(tái)的動(dòng)畫庫(kù)為我們的web項(xiàng)目,對(duì)于強(qiáng)調(diào)、主頁(yè)、滑動(dòng)、注意力引導(dǎo)非常有用;
如何使用Animate庫(kù)呢? 第一步:需要安裝animate.css庫(kù); 第二步:導(dǎo)入animate.css庫(kù)的樣式; 第三步:使用animation動(dòng)畫或者animate提供的類;
十三、自定義過(guò)渡class
我們可以通過(guò)以下 attribute 來(lái)自定義過(guò)渡類名:
enter-from-class enter-active-class enter-to-class leave-from-class leave-active-class leave-to-class
他們的優(yōu)先級(jí)高于普通的類名,這對(duì)于 Vue 的過(guò)渡系統(tǒng)和其他第三方 CSS 動(dòng)畫庫(kù),如 Animate.css. 結(jié)合使用十 分有用
十四、animate.css庫(kù)的使用
安裝animate.css:
npm install animate
. css
在main.js中導(dǎo)入animate.css:
接下來(lái)在使用的時(shí)候我們有兩種用法:
十五、認(rèn)識(shí)gsap庫(kù)
某些情況下我們希望通過(guò)JavaScript來(lái)實(shí)現(xiàn)一些動(dòng)畫的效果,這個(gè)時(shí)候我們可以選擇使用gsap庫(kù)來(lái)完成。
什么是gsap呢?
GSAP是The GreenSock Animation Platform(GreenSock動(dòng)畫平臺(tái))的縮寫; 它可以通過(guò)JavaScript為CSS屬性、SVG、Canvas等設(shè)置動(dòng)畫,并且是瀏覽器兼容的;
這個(gè)庫(kù)應(yīng)該如何使用呢? 第一步:需要安裝gsap庫(kù); 第二步:導(dǎo)入gsap庫(kù); p第三步:使用對(duì)應(yīng)的api即可;
我們可以先安裝一下gsap庫(kù):
npm install gsap
十六、JavaScript鉤子
在使用動(dòng)畫之前,我們先來(lái)看一下transition組件給我們提供的JavaScript鉤子,這些鉤子可以幫助我們監(jiān)聽(tīng)動(dòng)畫執(zhí)行到 什么階段了。
< template
> < div
class = "app" > < div
> < button @click
= "isShow = !isShow" > 顯示
/ 隱藏
< / button
> < / div
> < transition@before
- enter
= "beforeEnter" @enter
= "enter" @after
- enter
= "afterEnter" @before
- leave
= "beforeLeave" @leave
= "leave" @after
- leave
= "afterLeave" > < h2
class = "title" v
- if = "isShow" > hello
< / h2
> < / transition
> < / div
>
< / template
>
< script
> export default { name
: "App" , data ( ) { return { isShow
: true } } , methods
: { beforeEnter ( ) { console
. log ( 'beforeEnter' ) } , enter ( ) { console
. log ( 'enter' ) } , afterEnter ( ) { console
. log ( 'afterEnter' ) } , beforeLeave ( ) { console
. log ( 'beforeLeave' ) } , leave ( ) { console
. log ( 'leave' ) } , afterLeave ( ) { console
. log ( 'afterLeave' ) } }
}
< / script
>
< style scoped
>
. title
{ display
: inline
- block
;
}
< / style
>
當(dāng)我們使用JavaScript來(lái)執(zhí)行過(guò)渡動(dòng)畫時(shí),需要進(jìn)行 done 回調(diào),否則它們將會(huì)被同步調(diào)用,過(guò)渡會(huì)立即完成。
添加 :css=“false”,也會(huì)讓 Vue 會(huì)跳過(guò) CSS 的檢測(cè),除了性能略高之外,這可以避免過(guò)渡過(guò)程中 CSS 規(guī)則的影響。
十七、gsap庫(kù)的使用
那么接下來(lái)我們就可以結(jié)合gsap庫(kù)來(lái)完成動(dòng)畫效果:
十八、gsap實(shí)現(xiàn)數(shù)字變化
在一些項(xiàng)目中,我們會(huì)見(jiàn)到數(shù)字快速變化的動(dòng)畫效果,這個(gè)動(dòng)畫可以很容易通過(guò)gsap來(lái)實(shí)現(xiàn):
< template
> < div
class = "app" > < input type
= "number" step
= "100" v
- model
= "counter" > < h2
> { { showCounter
} } < / h2
> < h2
> { { showNumber
. toFixed ( 0 ) } } < / h2
> < / div
>
< / template
>
< script
>
import gsap
from 'gsap'
export default { name
: "App" , data ( ) { return { counter
: 0 , showNumber
: 0 } } , computed
: { showCounter ( ) { return this . showNumber
. toFixed ( 0 ) } } , watch
: { counter ( newValue ) { gsap
. to ( this , { duration
: 1 , showNumber
: newValue
} ) } }
}
< / script
>
< style scoped
>
< / style
>
十九、認(rèn)識(shí)列表的過(guò)渡
目前為止,過(guò)渡動(dòng)畫我們只要是針對(duì)單個(gè)元素或者組件的:
要么是單個(gè)節(jié)點(diǎn); 要么是同一時(shí)間渲染多個(gè)節(jié)點(diǎn)中的一個(gè);
那么如果希望渲染的是一個(gè)列表,并且該列表中添加刪除數(shù)據(jù)也希望有動(dòng)畫執(zhí)行呢?
這個(gè)時(shí)候我們要使用 <transition-group> 組件來(lái)完成;
使用<transition-group> 有如下的特點(diǎn):
默認(rèn)情況下,它不會(huì)渲染一個(gè)元素的包裹器,但是你可以指定一個(gè)元素并以 tag attribute 進(jìn)行渲染; 過(guò)渡模式不可用,因?yàn)槲覀儾辉傧嗷デ袚Q特有的元素; 內(nèi)部元素總是需要提供唯一的 key attribute 值; CSS 過(guò)渡的類將會(huì)應(yīng)用在內(nèi)部的元素中,而不是這個(gè)組/容器本身;
二十、列表過(guò)渡的基本使用
我們來(lái)做一個(gè)案例:
案例是一列數(shù)字,可以繼續(xù)添加或者刪除數(shù)字; 在添加和刪除數(shù)字的過(guò)程中,對(duì)添加的或者移除的數(shù)字添加動(dòng)畫;
< template
> < div
class = "app" > < button @click
= "addNum" > 添加數(shù)字
< / button
> < button @click
= "removeNum" > 刪除數(shù)字
< / button
> < transition
- group tag
= "p" name
= "zep" > < span
class = "item" v
- for = "item in numbers" : key
= "item" > { { item
} } < / span
> < / transition
- group
> < / div
>
< / template
>
< script
>
export default { name
: "App" , 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 ) } , randomIndex ( ) { return Math
. floor ( Math
. random ( ) * this . numbers
. length
) } }
}
< / script
>
< style scoped
> . item
{ margin
- right
: 10 px
; display
: inline
- block
; } . zep
- enter
- from , . zep
- leave
- to
{ opacity
: 0 ; transform
: translateY ( 30 px
) ; } . zep
- enter
- to
, . zep
- leave
- from { opacity
: 1 ; transform
: translateY ( 0 px
) ; } . zep
- enter
- active
, . zep
- leave
- active
{ transition
: all
1 s ease
; }
< / style
>
二十一、列表過(guò)渡的移動(dòng)動(dòng)畫
在上面的案例中雖然新增的或者刪除的節(jié)點(diǎn)是有動(dòng)畫的,但是對(duì)于哪些其他需要移動(dòng)的節(jié)點(diǎn)是沒(méi)有動(dòng)畫的:
我們可以通過(guò)使用一個(gè)新增的 v-move 的class來(lái)完成動(dòng)畫; 它會(huì)在元素改變位置的過(guò)程中應(yīng)用; 像之前的名字一樣,我們可以通過(guò)name來(lái)自定義前綴; 增加洗牌效果:
< template
> < div
class = "app" > < button @click
= "addNum" > 添加數(shù)字
< / button
> < button @click
= "removeNum" > 刪除數(shù)字
< / button
> < button @click
= "shuffleNum" > 洗牌
< / button
> < transition
- group tag
= "p" name
= "zep" > < span
class = "item" v
- for = "item in numbers" : key
= "item" > { { item
} } < / span
> < / transition
- group
> < / div
>
< / template
>
< script
>
import gsap
from 'gsap'
import _
from 'lodash'
export default { name
: "App" , 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 ) } , randomIndex ( ) { return Math
. floor ( Math
. random ( ) * this . numbers
. length
) } , shuffleNum ( ) { this . numbers
= _
. shuffle ( this . numbers
) } }
}
< / script
>
< style scoped
> . item
{ margin
- right
: 10 px
; display
: inline
- block
; } . zep
- enter
- from , . zep
- leave
- to
{ opacity
: 0 ; transform
: translateY ( 30 px
) ; } . zep
- enter
- to
, . zep
- leave
- from { opacity
: 1 ; transform
: translateY ( 0 px
) ; } . zep
- enter
- active
, . zep
- leave
- active
{ transition
: all
1 s ease
; } . zep
- leave
- active
{ position
: absolute
; } . zep
- move
{ transition
: transform
1 s ease
; }
< / style
>
二十二、列表的交錯(cuò)過(guò)渡案例
使用css過(guò)渡動(dòng)畫:達(dá)不到一個(gè)一個(gè)消失的效果,而是全部一起消失
我們來(lái)通過(guò)gsap的延遲delay屬性,做一個(gè)交替消失的動(dòng)畫:
< template
> < div
class = "app" > < input type
= "text" v
- model
= "keyword" > < transition
- group tag
= "ul" name
= "zep" : css
= "false" @before
- enter
= "beforeEnter" @enter
= "enter" @leave
= "leave" > < li v
- for = "(item, index) in showNames" : data
- index
= "index" : key
= "item" > { { item
} } < / li
> < / transition
- group
> < / div
>
< / template
>
< script
>
import gsap
from 'gsap'
export default { name
: "App" , data ( ) { return { names
: [ 'abc' , 'cba' , 'nba' , 'why' , 'lilei' , 'bob' , 'zep' ] , keyword
: '' } } , computed
: { showNames ( ) { return this . names
. filter ( ( item ) => { return 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.5rem' , delay
: el
. dataset
. index
* 0.5 , onComplete
: done
} ) } , leave ( el, done ) { gsap
. to ( el
, { opacity
: 0 , height
: '0rem' , delay
: el
. dataset
. index
* 0.5 , onComplete
: done
} ) } }
}
< / script
>
< style scoped
>
< / style
>
總結(jié)
以上是生活随笔 為你收集整理的Vue3过渡动画实现 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。