ข้ามไปเนื้อหาหลัก

Category: guide

GSAP Animation Guide — คู่มือ Animation ที่ทุก Frontend ควรรู้

GSAP คืออะไร ทำงานยังไง และวิธีใช้งานจริงในโปรเจกต์ — ตั้งแต่ gsap.to() พื้นฐานไปถึง ScrollTrigger และ Timeline

· อ่านประมาณ 8 นาที

สารบัญ

GSAP คืออะไร

GSAP (GreenSock Animation Platform) คือ JavaScript animation library ที่เน้นประสิทธิภาพสูงสุดและใช้งานง่าย มันเร็วกว่า CSS animation ในหลายกรณี และรองรับ browser ได้ดีกว่า Web Animations API

npm install gsap

Core Concepts

gsap.to() — animate ไปยังค่าปลายทาง

gsap.to('.box', {
  x: 200,
  opacity: 0,
  duration: 1,
  ease: 'power2.out',
});

gsap.from() — animate จากค่าต้นทาง

gsap.from('.hero-title', {
  y: -30,
  opacity: 0,
  duration: 0.5,
});

gsap.fromTo() — กำหนดค่าเริ่มต้นและปลายทางเอง

gsap.fromTo('.card',
  { y: 40, opacity: 0 },
  { y: 0,  opacity: 1, duration: 0.6, ease: 'power2.out' }
);

Timeline — เรียง animation ต่อกัน

const tl = gsap.timeline({ defaults: { ease: 'power2.out' } });

tl.from('.nav',    { y: -20, opacity: 0, duration: 0.4 })
  .from('.hero h1',{ y: 16,  opacity: 0, duration: 0.5 }, '-=0.2')
  .from('.hero p', { opacity: 0, duration: 0.4 }, '-=0.2');

-=0.2 คือ overlap: เริ่ม 0.2s ก่อน animation ก่อนหน้าจะจบ ทำให้ดูลื่น


Stagger — หลาย element ทยอยเล่น

gsap.from('.content-card', {
  y: 24,
  opacity: 0,
  duration: 0.45,
  stagger: 0.07,   // delay ระหว่างแต่ละ element
  ease: 'power2.out',
  clearProps: 'all',  // ลบ inline style หลัง animate จบ
});

ScrollTrigger Plugin

import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);

gsap.from('.section-header', {
  x: -20,
  opacity: 0,
  duration: 0.5,
  ease: 'power2.out',
  scrollTrigger: {
    trigger: '.section-header',
    start: 'top 88%',   // trigger เมื่อ top ของ element อยู่ที่ 88% จากบนหน้าจอ
    once: true,          // เล่นครั้งเดียว
  },
});

gsap.context() — memory management

ใช้เมื่อต้องการ cleanup animation เช่นใน SPA หรือ View Transitions

let ctx = gsap.context(() => {
  gsap.from('.hero', { opacity: 0, y: 20, duration: 0.5 });
  // ScrollTrigger ทั้งหมดใน context นี้จะถูก cleanup ด้วย ctx.revert()
});

// cleanup
ctx.revert();

Easings ที่ใช้บ่อย

Easeลักษณะ
power2.outเริ่มเร็ว ค่อยๆ ช้า — ใช้บ่อยที่สุด
power2.inเริ่มช้า เร็วขึ้น — ใช้กับ exit animation
power2.inOutช้า-เร็ว-ช้า — smooth ทั้งสองฝั่ง
back.out(1.5)เกิน target แล้วดีด กลับ — ใช้กับ scale/popup
elastic.out(1, 0.3)สปริง — เหมาะกับ UI ที่ playful

Accessibility: prefers-reduced-motion

if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
  // ใส่ animation ทั้งหมดไว้ใน block นี้
  gsap.from('.hero', { opacity: 0, duration: 0.5 });
}

ใช้งานกับ Astro + View Transitions

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

gsap.registerPlugin(ScrollTrigger);
let ctx: gsap.Context | null = null;

function init() {
  if (ctx) { ctx.revert(); ctx = null; }
  if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;

  ctx = gsap.context(() => {
    // animations ทั้งหมด
  });
}

document.addEventListener('astro:before-swap', () => {
  ScrollTrigger.getAll().forEach(st => st.kill());
  ctx?.revert();
});

document.addEventListener('astro:page-load', init);

clearProps: ‘all’ — ทำไมต้องใช้

เมื่อ animation จบ GSAP จะปล่อย inline style ค้างไว้บน element ซึ่งอาจทำให้ CSS class หรือ theme-switch ทำงานผิดพลาด clearProps: 'all' จะลบ inline style ทันทีหลัง animate จบ

gsap.from('.card', {
  opacity: 0,
  y: 20,
  clearProps: 'all',  // ✓ สำคัญมาก โดยเฉพาะกับ dark mode
});