GSAP3:專門處理動畫與特效的 JS 套件

本站不會更新了
新家網址:https://chupai.github.io/
文章:https://chupai.github.io/posts/200229_gsap3/

這週是 w3HexSchool 第四週,之前沒碰過 TweenMax,但 gsap 已經升級 GSAP3,就簡單研究一下 GSAP3。

GSAP3

GSAP 是 GreenSock Animation Platform 的簡稱,是一套專門處理動畫與特效的 JS 套件。

GSAP 採用模塊化與插件式的結構,保持了核心引擎的輕量。有四個核心 API,TweenLite、TimelinLite、TimelineMax、TweenMax,而 TweenMax 是所有 API 與 Plugin 的集合。

但 2019年底 GSAP 從 GSAP2 升級到 GSAP3,不再區分 TweenLite、TimelinLite、TimelineMax、TweenMax,全部合並為 gsap 物件。

GSAP3 的優點:

  • 檔案大小為 TweenMax 的一半,但新增了 50多個功能。
  • 全部合並為 gsap 物件,不用在區分 TweenLite 和 TimelineMax 物件。
  • 新版本相容舊版本寫法,所以可以沿用,新寫法提供更好的可讀性。

官網:

下載安裝

GSAP Installation

npm install gsap
// or
yarn add gsap

CDN

https://cdnjs.cloudflare.com/ajax/libs/gsap/3.1.1/gsap.min.js

版本差異

1. gsap 物件

原本須要用 Tweens(補間),就要使用 TweenLite/TweenMax 物件。要用到 Timelines(時間軸),就要使用 TimelineLite/TimelineMax 物件。

GSAP3 統一使用 gsap 物件。gsap 物件,具有各種方法和屬性,可用來創建 Tweens(補間)和 Timelines(時間軸)。

舊的 Tween 的創建方式:

TweenMax.method('selector', {});
// or
TweenLite.method('selector',{});

現在統一使用 gsap 物件:

gsap.method('selector', {});

舊的 Timeline 的創建方式:

const tl = new TimelineMax();

tl.method('selector', {});

// or
const tl = new TimelineLite();
tl.method('selector', {});

現在 Timeline 一樣也只需要使用 gsap 物件:

const tl = gsap.timeline();

tl.method('selector', {});

2. duration 參數

原來的寫法 duration 為方法的參數:

TweenMax.to('.box', 1, { x: 100 });

新寫法被整合到了 vars 物件中了:

gsap.to('.box', {
  duration: 1,
  x: 100,
});

擁有更佳的可讀性。

3. Timeline 預設值

原本的 Timeline 寫法:

const t = new TimelineMax();

t.to('.box1', 1, {
  x: 100,
  ease: 'elastic'
}).to('.box2', 1, {
  y: 100,
  ease: 'elastic'
});

使用新的寫法,如有有相同的參數,可以設定預設值:

const t = gsap.timeline({
  defaults: {
    duration: 1,
    ease: 'elastic'
  }
});

t.to('.box1', { x: 100 })
 .to('.box2', { y: 100 });

4. 交錯屬性

原本交錯動畫,要使用到額外的方法創建 Tween 實體,例如staggerTo()staggerFrom()staggerFromTo()

TweenMax.staggerTo('.box', 1, {rotation:360, x:100}, 0.5);

現在只需要設置 stagger 屬性即可:

gsap.to('.box', {
  duration: 1,
  stagger: 0.5,
  rotation: 360,
  x: 100
});

5. 全新的亂數功能

1 ~ 400 之間:

gsap.to('.box', {
  x: 'random(100, 400)',
});

隨機選擇一個數字,可以使用陣列表示:

gsap.to('.box', {
  x: 'random([0,100,400,500])',
});

6. 全新的影格功能 Keyframes

大家一定都知道 CSS 動畫的 keyframes。那 GSAP 中的 keyframes 是什麼?

原本要建立一連串的動畫(例如,先移動,再下移,最後旋轉),需要為每個動作建立 Tween 或使用 Timeline。而 keyframes 可以在同一個 Tween 內完成。

gsap.to('.box', {
  keyframes: [
    { duration: 1, x: 100, },
    { duration: 1, y: 100 },
    { duration: 1, rotation: 360 },
  ]
});

7. 全新的 repeatRefresh

開啟 repeatRefresh: true,會在重複執行時(設定 repeat),紀錄當前狀態再執行,而不會回到初始狀態。

gsap.to('.box', {
  duration: 1,
  repeat: 5,
  repeatRefresh: true,
  x: 'random(100, 400)',
});

8. 全新的全域動畫

Global timeline 可以控制全部的動畫實體。

gsap.globalTimeline.timeScale(0.1); // 控制所有動畫的速率 0 ~ 1
gsap.globalTimeline.pause();        // 停止目前所有動畫
gsap.globalTimeline.play();         // 播放目前所有動畫
gsap.globalTimeline.paused();       // 回傳目前動畫狀態 true:暫停 / false:播放

9. 新的動畫輔助工具

Utility Methods

  • gsap.utils.checkPrefix()
  • gsap.utils.clamp()
  • gsap.utils.distribute()
  • gsap.utils.getUnit()
  • gsap.utils.interpolate()
  • gsap.utils.mapRange()
  • gsap.utils.normalize()
  • gsap.utils.pipe()
  • gsap.utils.random()
  • gsap.utils.snap()
  • gsap.utils.splitColor()
  • gsap.utils.toArray()
  • gsap.utils.unitize()
  • gsap.utils.wrap()
  • gsap.utils.wrapYoyo()

10. 相對動畫時間

原本會需要標籤來添加相對動畫時間:

gsap.timeline()
  .add('s')
  .to('.box1', { ... }, 's')
  .to('.box2', { ... }, 's')
  .to('.box3', { ... }, 's+=0.8')
  .to('.box4', { ... }, 's+=0.8');

GSAP3 新增了最近的動畫時間:

  • >:最近添加的動畫的開始時間
  • <:最近添加的動畫的結束時間
gsap.timeline()
  .to('.box1', { ... })
  .to('.box2', { ... }, '<')
  .to('.box3', { ... }, '<0.8')
  .to('.box4', { ... }, '<');

補間動畫 Tween

補間是 flash 時代的專業詞彙,意思是在起始狀態和終點狀態之間補全中間過程。

包含四個要素:

  • 動畫目標(target)
  • 起始狀態
  • 終點狀態
  • 補間效果

1. 創建 Tween

創建 Tween 的常用方法(所有這些方法都會回傳 Tween 實體):

參數說明:

  • target:需要動畫的元素
    • target 使用 document.querySelectorAll(),所有符合的 CSS 選擇器都會是設置動畫的對象。
    • 如果有多個元素對象,則使用陣列 [element1, element2]
  • vars:設置補間效果及屬性狀態

Timeline

Timeline 就是「時間軸」,可以用來控制、管理一連串的動畫。

  • 控制多段動畫 / 序列動畫
  • 自由與重疊排序
  • 添加 Tag 掌握動畫片段

舉例來說,我們要對多個元素作一連串的動畫,需要建立多個 Tween 並用 delay 設置延遲時間,非常麻煩:

gsap.to('.box1', { duration: 1, x: 100, });
gsap.to('.box2', { delay: 1, duration: 1, y: 100 });
gsap.to('.box1', { delay: 2, duration: 1, rotation: 360 });

而且還無法對這一連串的動畫做控制。點我看範例

這時候可以使用 Timeline,建立一個時間軸,來管理這些動畫。

const t1 = gsap.timeline();

t1.to('.box1', { duration: 1, x: 100, })
  .to('.box2', { duration: 1, y: 100 })
  .to('.box1', { duration: 1, rotation: 360 });

點我看範例

如果有相同動畫狀態,可以設定預設值,使程式碼更簡潔:

const t1 = gsap.timeline({
  defaults: {
    duration: 1,
  },
});

t1.to('.box1', { x: 100, })
  .to('.box2', { y: 100, })
  .to('.box1', { rotation: 360, });

1. 在時間軸中放置動畫

在時間軸建立動畫:

  • to()
  • from
  • fromTo
  • set()
const tl = gsap.timeline();

tl.to(element, {duration: 1, x: 100, opacity: 0.5});

Timeline 可以鏈式呼叫:

const tl = gsap.timeline();

tl.from(element, {duration: 1, x: -100})
  .to(element, {duration: 1, y: 50});

在時間軸中,加入一段已建立的動畫,使用 add()

const tween = tween = gsap.to(element, {duration: 1, x: 100, opacity: 0.5});

const tl = gsap.timeline();
tl.add(tween);

Timeline 許多方法都多 position 參數,可用來控制動畫插入點:

  • 無設置:時間軸末尾
  • 1:絕對時間,指定時間處
  • '+=1'-=1:相對時間,相對於時間軸的結尾
  • 'someLabel':指定標籤處(建立標籤使用 addLabel()
  • ‵someLabel+=1'‵someLabel-=1':相對於指定標籤
  • <:最近動畫的開頭
  • >:最近動畫的結尾
  • <1<-1:相對於最近動畫的開頭
  • >1>-1:相對於最近動畫的結尾
// 插入至時間軸末尾
tl.to(element, 1, {});  

// 插入至時間軸2秒處
tl.to(element, 1, {}, 2);

// 在時間軸結束後2秒鐘插入
tl.to(element, 1, {}, '+=2');
// 在時間軸結束前2秒鐘插入
tl.to(element, 1, {}, '-=2');

// 在3秒處建立spin標籤
t1.addLabel('spin', 3);
// 在spin標籤處插入動畫
tl.to(element, 1, {}, 'spin');
// 在spin標籤處前三秒入動畫
tl.to(element, 1, {}, 'spin+=3');

// 在最近一次動畫的開頭插入
tl.to(element, {x: 100}, '<');

// 在最近一次動畫的開始後1秒插入
tl.to(element, {x: 100}, '<1');

基本用法

1. 數字動畫 0~100

最基本的用法,對物件的屬性去做變化。

2. CSS 動畫

3. 動畫控制

  • .play():播放動畫
  • .pause():暫停動畫播放
  • .paused():獲取或設置動畫暫停狀態
    • myAnimation.paused(!myAnimation.paused()) 暫停動畫切換
  • .resume():繼續動畫播放
  • .restart():重新開始動畫
  • .reverse():反轉播放動畫
  • .reversed():獲取或設置動畫反轉狀態
    • myAnimation.reversed( !myAnimation.reversed() ) 動畫撥放方向切換。
  • .seek():不改變狀態下,跳至動畫某個時間點

4. 重複撥放、來回撥放

repeat: 10,        // 設置動畫重複次數
repeatDelay: 0.5,  // 設置重複的間隔時間(秒)
yoyo: true,        // 設為true時,動畫會反轉重複

5. 錯開動畫

stagger: 0.5,  // 設置錯開時間

6. 週期

GSAP2 的 cycle 屬性,被 GSAP3 的 gsap.utils.wrap() 給取代,而且更加靈活。

簡易應用

Mousemove Event

1. Image Trail Effects

2. Slinky Text

Image Block Reveal

Text Animation

SplitText 商業插件

1. 重組文字