懶人包。
gsap.to()
設定動畫結束時的屬性。也就是說開始時的屬性會以原本 CSS 設定的屬性為主,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import { useEffect } from 'react' import { gsap } from 'gsap'
function App() { useEffect(() => { gsap.to('.square', { x: 300, duration: 1 }) }, [])
return ( <div className='App'> <div className='wrapper'> <div className='square'></div> </div> </div> ) }
export default App
|
如果我想自己控制動畫的播放/暫停之類的話怎麼辦?
基本上 gsap 大部分的 API 都會回傳一個「Tween」,直翻的話會翻成「補間動畫」,但我自己是理解成這段動畫的 instance,覺得這樣比較好懂一點。
所以剛剛的範例可以改寫成這樣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import { useEffect } from 'react' import { gsap } from 'gsap'
function App() { useEffect(() => { const tween = gsap.to('.square', { x: 300, duration: 1, paused: true })
document.querySelector('.play-btn')!.addEventListener('click', () => { tween.play() }) document.querySelector('.reverse-btn')!.addEventListener('click', () => { tween.reverse() }) }, [])
return ( <div className='App'> <div className='wrapper'> <div className='square'></div> </div> <button className='btn play-btn'>Start</button> <button className='btn reverse-btn'>Reverse</button> </div> ) }
export default App
|
我想要「按照順序」來播放動畫
如果單用 gsap.to()
的話可以透過 delay
來設定延遲時間,不過當動畫很複雜的時候也許你會想用 timeline
來處理,這個後面會在介紹,先不用太在意。
假設我們想實現這個效果:
附註:先往右邊移動後再往下移動。
那就能這樣子設定:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import { useEffect } from 'react' import { gsap } from 'gsap'
function App() { function demo() { gsap.to('.square', { x: 300, duration: 1 }) gsap.to('.square', { y: 300, delay: 1, duration: 1 }) }
return ( <div className='App'> <div className='wrapper'> <div className='square'></div> </div> <button className='btn' onClick={demo}> Start </button> </div> ) }
export default App
|
gsap.from()
跟 gsap.to
反過來的意思,這邊是決定動畫開始時的屬性,動畫結束時會回到原本在 CSS 設定的屬性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import { useEffect } from 'react' import { gsap } from 'gsap'
function App() { function demo() { gsap.from('.square', { x: 300, duration: 1 }) }
return ( <div className='App'> <div className='wrapper'> <div className='square'></div> </div> <button className='btn' onClick={demo}> Start </button> </div> ) }
export default App
|
gsap.fromTo()
當你不想要依據原本的 CSS 屬性來做動畫時,就可以直接用 gsap.fromTo()
來決定動畫開始與結束時的屬性:
附註:注意原本的位置在最前面,但按下 Start 後是動畫會從我們設定的位置開始,而不是原本 CSS 給的位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import { gsap } from 'gsap'
function App() { function demo() { gsap.fromTo( '.square', { x: 300, duration: 1 }, { x: 600, duration: 1 } ) }
return ( <div className='App'> <div className='wrapper'> <div className='square'></div> </div> <button className='btn' onClick={demo}> Start </button> </div> ) }
export default App
|
gsap.timeline()
gsap.timeline()
會回傳一個自動幫你處理「順序」的時間軸物件。
舉例來說如果想實作這樣的效果:
一個比較直覺的做法是透過 delay
來設定延遲時間,來實現「等 A 跑完後再跑 B」的效果,所以這邊 code 會長這樣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import { gsap } from 'gsap'
function App() { function demo() { gsap.to('.square1', { x: 300, duration: 1, ease: 'none' }) gsap.to('.square2', { x: 300, duration: 1, delay: 1, ease: 'none' }) }
return ( <div className='App'> <div className='wrapper'> <div className='square square1'></div> <div className='square square2'></div> </div> <button className='btn' onClick={demo}> Start </button> </div> ) } export default App
|
老實說這樣的做法沒什麼問題,唯一的缺點就是要計算每一個動畫的延遲時間還蠻麻煩的而已。
但如果用 gsap.timeline
來改寫的話會輕鬆許多:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import { gsap } from 'gsap'
function App() { function demo() { const timeline = gsap.timeline() timeline .to('.square1', { duration: 1, x: 300, ease: 'none' }) .to('.square2', { duration: 1, x: 300, ease: 'none' }) }
return ( <div className='App'> <div className='wrapper'> <div className='square square1'></div> <div className='square square2'></div> </div> <button className='btn' onClick={demo}> Start </button> </div> ) }
export default App
|
出來的結果是一模一樣的:
用時間軸的好處很明顯,就是你只要把按照順序去 call 對應的 function 就好,timeline
會自動幫我們搞定好延遲的問題。
位置參數(position parameter)
想要更精確的控制時間軸的話,可以加上第三個參數來做控制。詳細的部分可以參考 官方文件
1. 在時間軸的起始位置插入秒數(也可以想成時延遲秒數的意思)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import { gsap } from 'gsap'
function App() { function demo() { const timeline = gsap.timeline() timeline.to( '.square1', { duration: 1, x: 300, ease: 'none' }, 2 ) }
return ( <div className='App'> <div className='wrapper'> <div className='square square1'></div> </div> <button className='btn' onClick={demo}> Start </button> </div> ) }
export default App jk
|
2. 插入到前一個時間軸的起始點,換句話說就是「跟上一個時間軸同步」
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import { gsap } from 'gsap'
function App() { function demo() { const timeline = gsap.timeline() timeline.to('.square1', { duration: 1, x: 300, ease: 'none' }), timeline.to( '.square2', { duration: 1, x: 300, ease: 'none' }, '<' ) }
return ( <div className='App'> <div className='wrapper'> <div className='square square1'></div> <div className='square square2'></div> </div> <button className='btn' onClick={demo}> Start </button> </div> ) }
export default App
|
3. 插入到前一個時間軸的終點,其實就跟預設值一樣,會「依照順序」來執行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import { gsap } from 'gsap'
function App() { function demo() { const timeline = gsap.timeline() timeline.to('.square1', { duration: 1, x: 300, ease: 'none' }), timeline.to( '.square2', { duration: 1, x: 300, ease: 'none' }, '>' ) }
return ( <div className='App'> <div className='wrapper'> <div className='square square1'></div> <div className='square square2'></div> </div> <button className='btn' onClick={demo}> Start </button> </div> ) }
export default App
|