生活随笔
收集整理的這篇文章主要介紹了
Vue3过渡动画实现
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一、認識動畫
在開發(fā)中,我們想要給一個組件的顯示和消失添加某種過渡動畫,可以很好的增加用戶體驗:
React框架本身并沒有提供任何動畫相關(guān)的API,所以在React中使用過渡動畫我們需要使用一個第三方庫react-transition-group; Vue中為我們提供一些內(nèi)置組件和對應的API來完成動畫,利用它們我們可以方便的實現(xiàn)過渡動畫效果;
我們來看一個案例:
Hello World的顯示和隱藏; 通過下面的代碼實現(xiàn),是不會有任何動畫效果的;
沒有動畫的情況下,整個內(nèi)容的顯示和隱藏會非常的生硬:
如果我們希望給單元素或者組件 實現(xiàn)過渡動畫,可以使用 transition 內(nèi)置組件 來完成動畫;
二、Vue的transition動畫
Vue 提供了 transition 的封裝組件,在下列情形中,可以給任何元素和組件添加進入/離開過渡:
條件渲染 (使用 v-if)條件展示 (使用 v-show) 動態(tài)組件 組件根節(jié)點
< 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組件的原理
我們會發(fā)現(xiàn),Vue自動給h2元素添加了動畫,這是什么原因呢? 當插入或刪除包含在 transition 組件中的元素時,Vue 將會做以下處理:
1.自動嗅探目標元素是否應用了CSS過渡或者動畫,如果有,那么在恰當?shù)臅r機添加/刪除 CSS類名; 2.如果 transition 組件提供了JavaScript鉤子函數(shù),這些鉤子函數(shù)將在恰當?shù)臅r機被調(diào)用; 3.如果沒有找到JavaScript鉤子并且也沒有檢測到CSS過渡/動畫,DOM插入、刪除操作將會立即執(zhí)行;
那么都會添加或者刪除哪些class呢?
四、過渡動畫class
我們會發(fā)現(xiàn)上面提到了很多個class,事實上Vue就是幫助我們在這些class之間來回切換完成的動畫:
v-enter-from:定義進入過渡的開始狀態(tài)。在元素被插入之前生效,在元素被插入之后的下一幀移除。 v-enter-active:定義進入過渡生效時的狀態(tài)。在整個進入過渡的階段中應用,在元素被插入之前生效,在過渡/動畫完成之后移除。這個類可以被用來定義進入過渡的過程時間,延遲和曲線函數(shù)。 v-enter-to:定義進入過渡的結(jié)束狀態(tài)。在元素被插入之后下一幀生效 (與此同時 v-enter-from 被移除),在過渡/動畫完成之后移除。 v-leave-from:定義離開過渡的開始狀態(tài)。在離開過渡被觸發(fā)時立刻生效,下一幀被移除。 v-leave-active:定義離開過渡生效時的狀態(tài)。在整個離開過渡的階段中應用,在離開過渡被觸發(fā)時立刻生效,在過渡/動畫完成之后移除。這個類可以被用來定義離開過渡的過程時間,延遲和曲線函數(shù)。 v-leave-to:離開過渡的結(jié)束狀態(tài)。在離開過渡被觸發(fā)之后下一幀生效 (與此同時 v-leave-from 被刪除),在過渡/動畫完成之后移除。
五、class添加的時機和命名規(guī)則
class的name命名規(guī)則如下:
如果我們使用的是一個沒有name的transition ,那么所有的class是以 v- 作為默認前綴 ; 如果我們添加了一個name屬性,比如 <transtion name="zep">,那么所有的class會以 zep- 開頭 ;
六、過渡css動畫
前面我們是通過transition來實現(xiàn)的動畫效果,另外我們也可以通過animation來實現(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è)置過渡和動畫
Vue為了知道過渡的完成,內(nèi)部是在監(jiān)聽 transitionend 或 animationend,到底使用哪一個取決于元素應用的CSS規(guī)則:
如果我們只是使用了其中的一個,那么Vue能自動識別類型并設(shè)置監(jiān)聽;
但是如果我們同時使用了過渡和動畫呢?
并且在這個情況下可能某一個動畫執(zhí)行結(jié)束時,另外一個動畫還沒有結(jié)束; 在這種情況下,我們可以設(shè)置 type 屬性為 animation 或者 transition 來明確的告知Vue監(jiān)聽的類型;
注意: type值選擇animation還是transition? 誰的持續(xù)時間長選擇誰,以確保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
>
八、顯示的指定動畫時間
我們也可以顯示的來指定過渡的時間,通過 duration 屬性。
duration可以設(shè)置兩種類型的值:
number類型:同時設(shè)置進入和離開的過渡時間; object類型:分別設(shè)置進入和離開的過渡時間;
九、過渡的模式mode
我們來看當前的動畫在兩個元素之間切換的時候存在的問題: 我們會發(fā)現(xiàn) Hello World 和 你好啊,李銀河是同時存在的:
這是因為默認情況下進入和離開動畫是同時發(fā)生的 ; 如果確實我們希望達到這個的效果,那么是沒有問題;
但是如果我們不希望同時執(zhí)行進入和離開動畫,那么我們需要設(shè)置transition的過渡模式:
十、動態(tài)組件的切換
上面的示例同樣適用于我們的動態(tài)組件:
十一、appear初次渲染
默認情況下,首次渲染的時候是沒有動畫的,如果我們希望給他添加上去動畫,那么就可以增加另外一個屬性appear:
十二、認識animate.css
如果我們手動一個個來編寫這些動畫,那么效率是比較低的,所以在開發(fā)中我們可能會引用一些第三方庫的動畫庫, 比如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是一個已經(jīng)準備好的、跨平臺的動畫庫為我們的web項目,對于強調(diào)、主頁、滑動、注意力引導非常有用;
如何使用Animate庫呢? 第一步:需要安裝animate.css庫; 第二步:導入animate.css庫的樣式; 第三步:使用animation動畫或者animate提供的類;
十三、自定義過渡class
我們可以通過以下 attribute 來自定義過渡類名:
enter-from-class enter-active-class enter-to-class leave-from-class leave-active-class leave-to-class
他們的優(yōu)先級高于普通的類名,這對于 Vue 的過渡系統(tǒng)和其他第三方 CSS 動畫庫,如 Animate.css. 結(jié)合使用十 分有用
十四、animate.css庫的使用
安裝animate.css:
npm install animate
. css
在main.js中導入animate.css:
接下來在使用的時候我們有兩種用法:
十五、認識gsap庫
某些情況下我們希望通過JavaScript來實現(xiàn)一些動畫的效果,這個時候我們可以選擇使用gsap庫來完成。
什么是gsap呢?
GSAP是The GreenSock Animation Platform(GreenSock動畫平臺)的縮寫; 它可以通過JavaScript為CSS屬性、SVG、Canvas等設(shè)置動畫,并且是瀏覽器兼容的;
這個庫應該如何使用呢? 第一步:需要安裝gsap庫; 第二步:導入gsap庫; p第三步:使用對應的api即可;
我們可以先安裝一下gsap庫:
npm install gsap
十六、JavaScript鉤子
在使用動畫之前,我們先來看一下transition組件給我們提供的JavaScript鉤子,這些鉤子可以幫助我們監(jiān)聽動畫執(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
>
當我們使用JavaScript來執(zhí)行過渡動畫時,需要進行 done 回調(diào),否則它們將會被同步調(diào)用,過渡會立即完成。
添加 :css=“false”,也會讓 Vue 會跳過 CSS 的檢測,除了性能略高之外,這可以避免過渡過程中 CSS 規(guī)則的影響。
十七、gsap庫的使用
那么接下來我們就可以結(jié)合gsap庫來完成動畫效果:
十八、gsap實現(xiàn)數(shù)字變化
在一些項目中,我們會見到數(shù)字快速變化的動畫效果,這個動畫可以很容易通過gsap來實現(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
>
十九、認識列表的過渡
目前為止,過渡動畫我們只要是針對單個元素或者組件的:
要么是單個節(jié)點; 要么是同一時間渲染多個節(jié)點中的一個;
那么如果希望渲染的是一個列表,并且該列表中添加刪除數(shù)據(jù)也希望有動畫執(zhí)行呢?
這個時候我們要使用 <transition-group> 組件來完成;
使用<transition-group> 有如下的特點:
默認情況下,它不會渲染一個元素的包裹器,但是你可以指定一個元素并以 tag attribute 進行渲染; 過渡模式不可用,因為我們不再相互切換特有的元素; 內(nèi)部元素總是需要提供唯一的 key attribute 值; CSS 過渡的類將會應用在內(nèi)部的元素中,而不是這個組/容器本身;
二十、列表過渡的基本使用
我們來做一個案例:
案例是一列數(shù)字,可以繼續(xù)添加或者刪除數(shù)字; 在添加和刪除數(shù)字的過程中,對添加的或者移除的數(shù)字添加動畫;
< 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
>
二十一、列表過渡的移動動畫
在上面的案例中雖然新增的或者刪除的節(jié)點是有動畫的,但是對于哪些其他需要移動的節(jié)點是沒有動畫的:
我們可以通過使用一個新增的 v-move 的class來完成動畫; 它會在元素改變位置的過程中應用; 像之前的名字一樣,我們可以通過name來自定義前綴; 增加洗牌效果:
< 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
>
二十二、列表的交錯過渡案例
使用css過渡動畫:達不到一個一個消失的效果,而是全部一起消失
我們來通過gsap的延遲delay屬性,做一個交替消失的動畫:
< 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过渡动画实现 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。