The Own Lab The Own Lab

GSAP 動畫入門

GSAP 與 Motion 的差異比較,以及 GSAP 核心 API、Timeline、ScrollTrigger 實務用法

Overview##

GSAP(GreenSock Animation Platform) 是一個專業級的 JavaScript 動畫函式庫。它不綁定任何框架,可以動畫化任何 JavaScript 可操作的數值——CSS 屬性、SVG、Canvas、甚至自訂物件。

選擇動畫工具之前,先理解兩大主流的根本差異。

GSAP vs Motion##

Motion(前身 Framer Motion)和 GSAP 代表兩種不同的動畫範式:

範式差異###

// Motion(宣告式):描述「要什麼狀態」
<motion.div animate={{ x: 100, opacity: 1 }} />;

// GSAP(命令式):描述「怎麼做動畫」
gsap.to('.box', { x: 100, opacity: 1, duration: 1 });

Motion 把動畫當作元件的 props,跟 React 的宣告式思維一致。GSAP 則是直接操作 DOM,告訴瀏覽器「把這個元素在 1 秒內移到 x: 100」。

比較表###

面向GSAPMotion
範式命令式宣告式
框架依賴無(原生 JS)React / Vue
學習曲線中等低(React 開發者)
DOM 操作直接操作(ref)自動管理
Timeline強大,精細控制陣列語法,較簡潔
ScrollTrigger內建插件,功能豐富whileInView props
Layout 動畫需手動計算layout prop 自動處理
Exit 動畫需手動管理AnimatePresence 自動處理
檔案大小~28KB(核心)~18KB
授權商用免費(部分插件付費)MIT

Timeline 寫法對比###

// GSAP:鏈式呼叫,精細控制時間點
const tl = gsap.timeline();
tl.to('h1', { opacity: 1, duration: 0.5 })
  .to('p', { y: 0, duration: 0.3 }, '-=0.2') // 提前 0.2s 開始
  .to('.btn', { scale: 1, duration: 0.4 });

// Motion:陣列語法,用 at 控制時間
animate([
  ['h1', { opacity: 1 }, { duration: 0.5 }],
  ['p', { y: 0 }, { duration: 0.3, at: '-0.2' }],
  ['.btn', { scale: 1 }, { duration: 0.4 }],
]);

React 整合對比###

// Motion:宣告式,跟 React 思維一致
function Card() {
  return (
    <motion.div
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0 }}
      whileHover={{ scale: 1.05 }}
    />
  );
}

// GSAP:命令式,需要 ref + useGSAP hook
function Card() {
  const container = useRef();

  useGSAP(
    () => {
      gsap.from('.card', { opacity: 0, y: 20, duration: 0.5 });
    },
    { scope: container },
  );

  return (
    <div ref={container}>
      <div className="card" />
    </div>
  );
}

選擇指南###

場景推薦
React UI 互動(hover、進場、離場)Motion
複雜序列動畫、精細時間軸控制GSAP
捲動驅動動畫(ScrollTrigger)GSAP
跨框架或原生 JS 專案GSAP
Layout 動畫(元素位置切換)Motion
需要商用免費的完整方案依需求評估授權

Tip

兩者不互斥。在同一個專案中,可以用 Motion 處理 UI 互動動畫,用 GSAP 處理複雜的捲動和序列動畫。

Core API##

GSAP 的核心只有三個方法:tofromfromTo

gsap.to()###

目前狀態動畫到目標狀態——最常用的方法:

// 在 1 秒內,把 .box 移到 x: 200 並淡出
gsap.to('.box', {
  x: 200,
  opacity: 0,
  duration: 1,
});

gsap.from()###

指定狀態動畫到目前狀態——適合進場動畫:

// .box 從 opacity: 0、y: -50 的位置動畫到原始位置
gsap.from('.box', {
  opacity: 0,
  y: -50,
  duration: 0.8,
});

gsap.fromTo()###

同時指定起點終點——完全控制:

gsap.fromTo(
  '.box',
  { opacity: 0, x: -100 }, // from
  { opacity: 1, x: 0, duration: 1 }, // to
);

常用屬性###

屬性說明範例
x / y位移(transform)x: 100(等同 translateX)
rotation旋轉(度)rotation: 360
scale縮放scale: 1.5
opacity透明度opacity: 0
duration動畫時長(秒)duration: 1
delay延遲開始(秒)delay: 0.5
ease緩動函數ease: "power2.out"
stagger多元素依序動畫的間隔stagger: 0.1

Ease###

緩動函數決定動畫的速度曲線:

// 常用 ease
gsap.to('.box', { x: 200, ease: 'power1.out' }); // 輕微減速
gsap.to('.box', { x: 200, ease: 'power2.inOut' }); // 先加速後減速
gsap.to('.box', { x: 200, ease: 'bounce.out' }); // 彈跳效果
gsap.to('.box', { x: 200, ease: 'elastic.out' }); // 彈性效果
gsap.to('.box', { x: 200, ease: 'back.out(1.7)' }); // 超出後回彈
Ease效果
"none"線性(等速)
"power1" ~ "power4"漸進式加/減速,數字越大越明顯
"bounce"彈跳
"elastic"彈性
"back"超出後回彈
.in / .out / .inOut加速 / 減速 / 先加後減

Tip

GSAP 提供 Ease Visualizer 讓你視覺化每種緩動函數的效果。選擇 ease 時建議先在 visualizer 上測試。

Stagger###

讓多個元素依序動畫,而不是同時開始:

// 5 個 .card 元素,每個間隔 0.15 秒依序淡入
gsap.from('.card', {
  opacity: 0,
  y: 30,
  duration: 0.5,
  stagger: 0.15,
});

// 進階:從中間向兩側展開
gsap.from('.card', {
  opacity: 0,
  scale: 0,
  stagger: {
    each: 0.1,
    from: 'center',
  },
});

Timeline##

單個 gsap.to() 只能做一段動畫。Timeline 讓你編排多段動畫的順序和時間:

const tl = gsap.timeline();

// 預設:依序播放
tl.to('.title', { opacity: 1, duration: 0.5 })
  .to('.subtitle', { opacity: 1, y: 0, duration: 0.3 })
  .to('.content', { opacity: 1, duration: 0.4 });

Position Parameter###

控制動畫在時間軸上的插入位置:

const tl = gsap.timeline();

tl.to('h1', { x: 100, duration: 1 })
  // 絕對時間:在 0.5 秒開始
  .to('h2', { x: 100, duration: 1 }, 0.5)
  // 相對時間:在上一個動畫結束前 0.2 秒開始
  .to('h3', { x: 100, duration: 1 }, '-=0.2')
  // 相對時間:在上一個動畫結束後 0.5 秒開始
  .to('h4', { x: 100, duration: 1 }, '+=0.5')
  // 同時開始:與上一個動畫同步
  .to('h5', { x: 100, duration: 1 }, '<');
Position說明
0.5絕對時間 0.5 秒
"-=0.2"前一個動畫結束前 0.2 秒
"+=0.5"前一個動畫結束後 0.5 秒
"<"與前一個動畫同時開始
">"前一個動畫結束時

Timeline 控制###

const tl = gsap.timeline({ paused: true });
tl.to('.box', { x: 200 }).to('.box', { y: 100 });

tl.play(); // 播放
tl.pause(); // 暫停
tl.reverse(); // 反轉播放
tl.restart(); // 重新開始
tl.progress(0.5); // 跳到 50%

Note

Timeline 可以巢狀——一個 Timeline 可以作為另一個 Timeline 的一段動畫,適合組織複雜的動畫場景。

ScrollTrigger##

ScrollTrigger 是 GSAP 最受歡迎的插件——讓動畫由捲動位置驅動。

基本用法###

import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

// 元素進入視窗時觸發動畫
gsap.from('.section', {
  opacity: 0,
  y: 50,
  duration: 1,
  scrollTrigger: {
    trigger: '.section', // 觸發元素
    start: 'top 80%', // 元素頂部到達視窗 80% 位置時開始
    end: 'bottom 20%', // 元素底部到達視窗 20% 位置時結束
  },
});

Scrub###

讓動畫進度跟捲動位置同步——捲多少,動畫就播多少:

gsap.to('.progress-bar', {
  width: '100%',
  scrollTrigger: {
    trigger: '.article',
    start: 'top top',
    end: 'bottom bottom',
    scrub: true, // 動畫跟著捲動走
  },
});

// scrub: 1 → 加上 1 秒的平滑延遲

Pin###

在捲動期間「釘住」元素:

gsap.to('.hero-text', {
  opacity: 0,
  scrollTrigger: {
    trigger: '.hero',
    start: 'top top',
    end: '+=500', // 釘住 500px 的捲動距離
    pin: true, // 釘住 trigger 元素
    scrub: true,
  },
});

Timeline + ScrollTrigger###

const tl = gsap.timeline({
  scrollTrigger: {
    trigger: '.container',
    pin: true,
    start: 'top top',
    end: '+=1000',
    scrub: 1,
    snap: {
      snapTo: 'labels',
      duration: { min: 0.2, max: 3 },
    },
  },
});

tl.addLabel('start')
  .from('.step-1', { opacity: 0, y: 50 })
  .addLabel('step1')
  .from('.step-2', { opacity: 0, y: 50 })
  .addLabel('step2')
  .from('.step-3', { opacity: 0, y: 50 })
  .addLabel('end');

Warning

ScrollTrigger 在 SPA 框架(React、Vue)中需要注意清理。元件卸載時必須呼叫 ScrollTrigger.kill() 或使用 useGSAP hook 自動管理生命週期。

Quiz##

Single Choice

GSAP 和 Motion 最根本的差異是什麼?

Single Choice

gsap.from('.box', { opacity: 0, y: -50 }) 的效果是什麼?

Single Choice

Timeline 中 position: '-=0.2' 的意思是什麼?

Single Choice

ScrollTrigger 的 scrub: true 有什麼效果?

Single Choice

以下哪個場景更適合用 Motion 而非 GSAP?

Summary##

  • GSAP = 命令式(精細控制),Motion = 宣告式(React 友善),兩者可共存
  • 核心 API 只有三個:to(目前→目標)、from(指定→目前)、fromTo(指定→指定)
  • ease 控制速度曲線,stagger 讓多元素依序動畫
  • Timeline 編排動畫序列,Position Parameter 控制時間點(-=0.2<+=0.5
  • ScrollTrigger 讓動畫由捲動驅動——scrub 同步進度、pin 釘住元素
  • SPA 框架中使用 ScrollTrigger 需注意清理,避免記憶體洩漏

留言 (0)

登入後即可留言