Category: guide
GSAP Animation Guide — คู่มือ Animation ที่ทุก Frontend ควรรู้
GSAP คืออะไร ทำงานยังไง และวิธีใช้งานจริงในโปรเจกต์ — ตั้งแต่ gsap.to() พื้นฐานไปถึง ScrollTrigger และ Timeline
สารบัญ
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
});