gsap について
Web アニメーションを作る開発者向けの GSAP スキルです。タイムライン、スクロール連動、スタッガーアニメーション、React 連携を扱い、実装上の注意点とパフォーマンスも説明します。
主な機能
- 01タイムラインによるアニメーション構成
- 02ScrollTrigger によるスクロール連動
- 03スタッガーと分布型アニメーション
- 04React useGSAP 連携
- 05アニメーション実装の注意点
活用シーン
- 01複数要素の連続アニメーション制作
- 02スクロール連動のページ演出
- 03React でのアニメーション後処理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ athevon/ genjutsu --skill gsapインストール後、Claude Code で/gsapを入力して読み込まれたか確認します。
詳細
バージョン依存の情報です。 以下のすべての API 名、SDK の要件、ブラウザーサポートに関する記述は、一次資料に基づき 2026-09-08 に確認済みです。何をいつ確認したかは
_jutsu/VERSIONS.mdをご覧ください。この日付が古い場合は、バージョン番号に基づいて作業する前に再確認してください。
GSAP - アニメーションエンジン
GSAP 3.15(2026 年 4 月 13 日リリース)。3.13 以降、以前の Club プラグイン(SplitText、MorphSVG、DrawSVG、ScrollSmoother、InertiaPlugin、MotionPathHelper、CustomEase など)を含むライブラリ全体が、パブリックな
gsapnpm パッケージで提供されており、GreenSock Standard「無料」ライセンスのもと、商用利用も含めて無料です。Club の有料プランはありません。 GreenSock は公式のエージェントスキル(MIT、8 スキル:core、timeline、scrolltrigger、plugins、utils、react、performance、frameworks)も公開しています:https://github.com/greensock/gsap-skills。このサブスキルと併せてインストールする価値があります。
GSAP を使用する場面
| 基準 | CSS Transitions | Framer Motion | GSAP |
|---|---|---|---|
| ホバー/単純な切り替え | はい | はい | 過剰 |
| シーケンス化されたタイムライン | いいえ | 限定的 | はい |
| スクロール連動 | scroll-timeline | 限定的 | ScrollTrigger |
| 複雑なスタガー | いいえ | 基本的 | Distribution |
| モバイル性能(60fps) | 良好 | 平均的 | 優秀 |
| テキスト分割 | いいえ | いいえ | SplitText |
| SVG のモーフィング/描画 | いいえ | いいえ | MorphSVG |
| バンドルサイズへの懸念 | 0kb | ~30kb | ~25kb + プラグイン |
ルール:タイムライン、スクロール連動、または分散スタガーが必要なアニメーションには GSAP を使用してください。それ以外は、まず CSS を使います。
セットアップ
// Always register plugins at the top level
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { SplitText } from "gsap/SplitText";
gsap.registerPlugin(ScrollTrigger, SplitText);
React では、useEffect と手動のクリーンアップの代わりに、@gsap/react パッケージの useGSAP() を使用してください。
import { useGSAP } from "@gsap/react";
useGSAP(() => {
gsap.to(".box", { x: 200 });
}, { scope: containerRef }); // auto-cleanup, auto-revert
基本パターン
繰り返しを避ける defaults{}
const tl = gsap.timeline({
defaults: { duration: 0.8, ease: "power2.out" },
});
tl.to(".a", { y: -20 })
.to(".b", { y: -20 }, "<0.1")
.to(".c", { y: -20 }, "<0.1");
完全に制御する fromTo
gsap.fromTo(".card", { y: 40, opacity: 0 }, { y: 0, opacity: 1, stagger: 0.15 });
分布によるスタガー
gsap.to(".grid-item", {
scale: 0,
stagger: {
each: 0.05,
from: "center", // "start" | "end" | "center" | "edges" | "random" | index
grid: "auto", // auto-detects the grid
axis: "x", // "x" | "y" | null (both)
},
});
ScrollTrigger のパターン
基本的なピン留め+スクラブ
gsap.to(".panel", {
x: "-300%",
ease: "none",
scrollTrigger: {
trigger: ".container",
pin: true,
scrub: 1,
end: () => "+=" + document.querySelector(".container").scrollWidth,
},
});
大量の要素を表示する Batch
ScrollTrigger.batch(".card", {
onEnter: (elements) => gsap.to(elements, { opacity: 1, y: 0, stagger: 0.1 }),
start: "top 85%",
});
containerAnimation を使った水平スクロール
const scrollTween = gsap.to(".panels", {
x: () => -(document.querySelector(".panels").scrollWidth - window.innerWidth),
ease: "none",
scrollTrigger: { trigger: ".wrapper", pin: true, scrub: 1 },
});
// Animate elements INSIDE the horizontal scroll
gsap.to(".panel-content", {
scale: 1.2,
scrollTrigger: {
trigger: ".panel-content",
containerAnimation: scrollTween, // linked to horizontal scroll
start: "left center",
end: "right center",
scrub: true,
},
});
やってはいけないこと - 重大なミス
1. containerAnimation での Ease
// BAD - ease breaks the scroll mapping
scrollTrigger: { containerAnimation: scrollTween, scrub: 1, ease: "power2.out" }
// GOOD - always ease: "none" on the parent tween
const scrollTween = gsap.to(".panels", { x: ..., ease: "none", scrollTrigger: { scrub: 1 } });
2. タイムライン内の子トゥイーンに対する ScrollTrigger
// BAD - ScrollTrigger ignores child tweens of a timeline that has its own ScrollTrigger
const tl = gsap.timeline({ scrollTrigger: { trigger: ".section" } });
tl.to(".box", { x: 100, scrollTrigger: { trigger: ".box" } }); // IGNORE
// GOOD - one ScrollTrigger per timeline OR standalone tweens
gsap.to(".box", { x: 100, scrollTrigger: { trigger: ".box" } }); // tween standalone
3. onUpdate での setState
// BAD - setState 60x/s = re-render hell
scrollTrigger: { onUpdate: (self) => setProgress(self.progress) }
// GOOD - mutate a ref or DOM element directly
const progressRef = useRef(0);
scrollTrigger: { onUpdate: (self) => { progressRef.current = self.progress; } }
// Or better: gsap.quickSetter to mutate the DOM without React
4. タイムライン内の from() での immediateRender
// BAD - from() has immediateRender: true by default, breaks sequencing
tl.to(".box", { x: 100 });
tl.from(".box", { y: 50 }); // visually jumps to the start
// GOOD - disable immediateRender when from() follows another tween
tl.to(".box", { x: 100 });
tl.from(".box", { y: 50, immediateRender: false });
5. transform 以外のプロパティのアニメーション
// BAD - width/height/top/left trigger layout reflow
gsap.to(".box", { width: 200, height: 200 });
// GOOD - use transforms (GPU-accelerated, composited)
gsap.to(".box", { scaleX: 1.5, scaleY: 1.5 });
// If actual size needed: use Flip plugin for layout transition
参考資料
references/core.md- gsap.to/from/fromTo/set API とオプションの完全な説明references/timeline.md- Timeline、position パラメーター、ネストreferences/scrolltrigger.md- ScrollTrigger の完全なリファレンスreferences/plugins.md- SplitText、Flip、MorphSVG、DrawSVG、MotionPath、Observer