Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

使用 GSAP 的 ScrollTrigger 製作捲動動畫

原本我是透過 AOS 這款 JavaScript 函式庫製作頁面捲動的動畫 (animation on scroll),但這次公司網站改版,需要較複雜的動畫,因此必須改用 GSAP 來製作更進階的捲動動畫。

首先,先分享實作結果,這是透過 ScrollTrigger 外掛,搭配 GSAP 中變更數值的方式,製作的數字跳動動畫。

See the Pen GSAP Integer Animation by Eric Chuang (@eric-chuang) on CodePen.

ScrollTrigger 簡介

ScrollTrigger 的基本語法如下:

/* 除了需要在 <head> 中引入 JavaScript 資源外,須在 JavaScript 中註冊外掛 */
gsap.registerPlugin(ScrollTrigger);

gsap.to("動畫物件選擇器", {
  scrollTrigger: "觸發選擇器",
  x: 500 // 向右移動 500px
});

scrollTrigger 這個屬性的屬性值,除了觸發條件的選擇器外,也可以用物件的方式來設定觸發條件。

gsap.to( "動畫物件選擇器",{
scrollTrigger: {
      trigger: "觸發選擇器",
      pin: true,   // 當動畫執行中的時候,讓觸發選擇器置頂
      start: "top top", 
      // 當觸發選擇器的頂端 (左邊的 top) 碰到檢視區頂端 (右邊的 top) 時啟用
      end: "+=500", 
      // 捲動 500px 後結束動畫
      scrub: 1, 
      // 是否根據捲動程度決定動畫完成程度,
      // 如果填寫數字,則在會延遲 n 秒後才到定位。
      snap: {
        // 貼齊效果
        snapTo: "labels",
        // 貼齊最近的標籤,須搭配 addLabel 方法
        duration: {
          min: 0.2,
          max: 3
        }, 
        // 貼齊動畫須慢於 0.2 秒,不超過 3 秒
        delay: 0.2, 
        // 捲動完畢後延遲 0.2 秒才會執行貼齊動畫
        ease: "power1.inOut"
        // 動畫加減速,預設是 power3
      }
    }
} );

讓 GSAP 控制數值

用 GSAP 來製作動畫的基本觀念,是變更「CSS 樣式屬性值」。

但其實不只 CSS 屬性值,一般的數值也可以用 GSAP 來控制,並用來製作計數器。這次實作參考的 Codepen 如下:

See the Pen Tweenmax Integer Tween by Nicolaj Lund Hummel (@nicolund) on CodePen.

首先,範例中先給了 counter 這個物件中的 var 屬性一個預設值 0。

接著,透過補間 (tween) 的方式,讓 counter 這個物件的 var 屬性值,在 5 秒內從 0 變成 100。

而在數值變化的過程中,藉由 onUpdate 這個方法,讓 var 屬性值反映在 #tal 顯示的值之上。

然而,因為這個範例只有選擇 #tal 這個元素,並不是我原本預期的,可以同時變更多個元素的樣式。因此做了下列的修改:首先,把 tal 從原本的 ID 選擇器,改成用 Class 類別的選擇器,因此在標記的過程中,我們將 tal 改為 CSS 類別:

<div class="tals">
  <div class="tal" data-end="10">
    0
  </div>
  <div class="tal" data-end="20">
    0
  </div>
  <div class="tal" data-end="30">
    0
  </div>
</div>
<!-- 自訂 data-end 這個資料屬性,用來儲存動畫最後的數值 -->

接著定義初始值 start

let start = { val: 0 };

透過 gsap.utils.toArray 這個函式,搭配 forEach,讓動畫效果可以套用到個別元素上。在這裡 trigger 需要以當前的物件 label 為選擇器,如果用 ".tal" 的方式作為選擇器,那麼只有第一個 .tal 會套用到動畫樣式。

gsap.utils.toArray( '.tal' ).forEach( function ( label ) {
  start.val = 0;
  // 這個作法的目的是歸零 start 的起始值,讓它可以重複利用
  gsap.to( start, {
    // 這裡需要注意的是,要變化的是 start.val 的數值,而不是改變 label 的物件
    duration: 1,
    scrollTrigger: {
      // 設定觸發條件
      trigger: label,
      // 以當前的 label 作為觸發條件
      toggleActions: "play none none none",
      // 不需要有任何回溯的效果,所以只有單向的 play
      start: "top center",
      // 當觸發選擇器的頂端碰到檢視區正中間時啟用
    },
    val: label.dataset.end,
    // 選取 data-end 資料屬性的值作為終點
    onUpdate: ( function () {
      label.innerHTML = Math.floor( Number( start.val ) );
      // 當 val 數值變更時,用 Math.floor 讓數字以整數形式呈現。
    } )
  } );
} );

結語

這次因為公司網站改版的關係,更深入的學習 GSAP,更強烈的感受到這是一套強大且方便的函式庫。如果對於前端有興趣的話,這是一套非常值得投資時間學習的函式庫。

參考資料

Eric Chuang
Eric Chuang

正職是廣告行銷人員,因為 Google Tag Manager 的關係開始踏入網站製作的領域,進一步把 WordPress 當成 PHP + HTML + CSS + JavaScript 的學習教材。此外,因為工作的關係,曾經用 Automattic 的 Underscores (_s) 替客戶與公司官網進行全客製化佈景主題開發。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料