gsap-scrolltrigger について
gsap-scrolltrigger は、GSAP ScrollTrigger でスクロール連動アニメーションや操作を作る開発者向けのリファレンススキルです。トリガー設定やスクロール効果の実装例を扱います。
主な機能
- 01トリガー位置と動作の設定
- 02スクロールとアニメーション進行の連動
- 03セクション固定とスナップ位置の設定
- 04視差効果と横スクロールの作成
- 05スクロールアニメーションの一括処理
- 06コールバックによる状態追跡
活用シーン
- 01画面内に入る要素の表示演出
- 02固定セクションを使った横スクロールページ
- 03スクロール進捗バーや視差背景の追加
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ bbeierle12/ skill-mcp-claude --skill gsap-scrolltriggerインストール後、Claude Code で/gsap-scrolltriggerを入力して読み込まれたか確認します。
同梱ファイル_meta.json
詳細
GSAP ScrollTrigger
スクロールに連動するアニメーションとインタラクションです。
クイックスタート
npm install gsap
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
gsap.to('.box', {
x: 500,
scrollTrigger: {
trigger: '.box',
start: 'top center',
end: 'bottom center',
scrub: true
}
});
基本概念
基本的な ScrollTrigger
gsap.to('.element', {
x: 200,
scrollTrigger: {
trigger: '.element', // Element that triggers the animation
start: 'top center', // When trigger hits viewport center
end: 'bottom center', // When trigger leaves viewport center
toggleActions: 'play pause resume reset'
}
});
開始位置/終了位置
// Format: "trigger-position viewport-position"
start: 'top center' // Trigger's top hits viewport center
start: 'top 80%' // Trigger's top hits 80% down viewport
start: 'center center' // Trigger's center hits viewport center
start: 'bottom top' // Trigger's bottom hits viewport top
start: 'top top+=100' // Trigger's top hits 100px below viewport top
位置の基準
| 値 | 説明 |
|---|---|
top | 上端 |
center | 中央 |
bottom | 下端 |
80% | 上端から80% |
+=100 | 100ピクセル加算 |
-=50 | 50ピクセル減算 |
スクラブアニメーション
基本的なスクラブ
// Animation progress tied to scroll position
gsap.to('.progress-bar', {
scaleX: 1,
scrollTrigger: {
trigger: '.content',
start: 'top top',
end: 'bottom bottom',
scrub: true // Directly linked to scroll
}
});
スムーズなスクラブ
gsap.to('.element', {
x: 500,
scrollTrigger: {
trigger: '.section',
scrub: 1, // 1 second smoothing
// scrub: 0.5 // 0.5 second smoothing
// scrub: 2 // 2 second smoothing (laggy feel)
}
});
タイムラインを使ったスクラブ
const tl = gsap.timeline({
scrollTrigger: {
trigger: '.container',
start: 'top top',
end: '+=3000', // Scroll distance
scrub: 1,
pin: true
}
});
tl.to('.step1', { opacity: 1 })
.to('.step2', { opacity: 1 })
.to('.step3', { opacity: 1 });
ピン留め
基本的なピン留め
ScrollTrigger.create({
trigger: '.panel',
start: 'top top',
end: '+=500', // Pin for 500px of scroll
pin: true
});
アニメーションを使ったピン留め
gsap.to('.content', {
x: '-200%',
ease: 'none',
scrollTrigger: {
trigger: '.horizontal-section',
start: 'top top',
end: () => '+=' + document.querySelector('.horizontal-section').offsetWidth,
pin: true,
scrub: 1
}
});
ピン留めの間隔
ScrollTrigger.create({
trigger: '.section',
pin: true,
pinSpacing: true, // Default: adds space for pinned duration
// pinSpacing: false // No extra space (content overlaps)
// pinSpacing: '500px' // Custom spacing
});
切り替えアクション
アクションの構文
// Format: "onEnter onLeave onEnterBack onLeaveBack"
toggleActions: 'play pause resume reset'
// Common combinations:
toggleActions: 'play none none none' // Play once
toggleActions: 'play reverse play reverse' // Toggle direction
toggleActions: 'restart none none none' // Restart each time
toggleActions: 'play complete reverse reset'
アクションの値
| アクション | 効果 |
|---|---|
play | 順方向に再生 |
pause | 一時停止 |
resume | 一時停止した位置から再開 |
reverse | 逆方向に再生 |
restart | 最初から再生 |
reset | アニメーションなしで開始位置にリセット |
complete | 終了位置にジャンプ |
none | 何もしない |
スナップ位置
基本的なスナップ
ScrollTrigger.create({
trigger: '.sections',
start: 'top top',
end: 'bottom bottom',
snap: 1 / 4 // Snap to quarters
});
ラベルへのスナップ
const tl = gsap.timeline({
scrollTrigger: {
trigger: '.container',
scrub: 1,
snap: {
snapTo: 'labels',
duration: 0.5,
ease: 'power2.inOut'
}
}
});
tl.addLabel('intro')
.to('.a', { opacity: 1 })
.addLabel('middle')
.to('.b', { opacity: 1 })
.addLabel('end');
スナップの設定
snap: {
snapTo: [0, 0.25, 0.5, 0.75, 1], // Snap to specific points
duration: { min: 0.2, max: 0.6 }, // Snap duration range
delay: 0, // Delay before snap
ease: 'power1.inOut', // Snap easing
directional: true // Snap in scroll direction
}
コールバック
ScrollTrigger のコールバック
ScrollTrigger.create({
trigger: '.section',
onEnter: () => console.log('Entered'),
onLeave: () => console.log('Left'),
onEnterBack: () => console.log('Entered from bottom'),
onLeaveBack: () => console.log('Left going up'),
onUpdate: (self) => console.log('Progress:', self.progress),
onToggle: (self) => console.log('Active:', self.isActive),
onRefresh: () => console.log('Refreshed')
});
進行度に基づく更新
ScrollTrigger.create({
trigger: '.section',
start: 'top bottom',
end: 'bottom top',
onUpdate: (self) => {
// self.progress: 0 to 1
// self.direction: 1 (down) or -1 (up)
// self.velocity: scroll speed
updateElement(self.progress);
}
});
パララックス効果
基本的なパララックス
// Background moves slower than scroll
gsap.to('.background', {
yPercent: -50,
ease: 'none',
scrollTrigger: {
trigger: '.section',
scrub: true
}
});
// Foreground moves faster
gsap.to('.foreground', {
yPercent: 50,
ease: 'none',
scrollTrigger: {
trigger: '.section',
scrub: true
}
});
複数レイヤーのパララックス
const layers = [
{ selector: '.layer-1', speed: -20 },
{ selector: '.layer-2', speed: -40 },
{ selector: '.layer-3', speed: -60 },
{ selector: '.layer-4', speed: -80 }
];
layers.forEach(layer => {
gsap.to(layer.selector, {
yPercent: layer.speed,
ease: 'none',
scrollTrigger: {
trigger: '.parallax-section',
start: 'top bottom',
end: 'bottom top',
scrub: true
}
});
});
横スクロール
横スクロールセクション
const sections = gsap.utils.toArray('.panel');
gsap.to(sections, {
xPercent: -100 * (sections.length - 1),
ease: 'none',
scrollTrigger: {
trigger: '.horizontal-container',
pin: true,
scrub: 1,
snap: 1 / (sections.length - 1),
end: () => '+=' + document.querySelector('.horizontal-container').offsetWidth
}
});
マーカー(開発時)
ScrollTrigger.create({
trigger: '.section',
start: 'top center',
end: 'bottom center',
markers: true, // Show visual markers
// markers: { startColor: 'green', endColor: 'red', fontSize: '12px' }
});
バッチアニメーション
スクロール時のスタッガー
ScrollTrigger.batch('.card', {
onEnter: (elements) => {
gsap.from(elements, {
opacity: 0,
y: 50,
stagger: 0.1,
duration: 0.5
});
},
start: 'top 85%'
});
バッチの設定
ScrollTrigger.batch('.item', {
interval: 0.1, // Time between batches
batchMax: 3, // Max items per batch
onEnter: batch => gsap.to(batch, { opacity: 1, y: 0, stagger: 0.1 }),
onLeave: batch => gsap.to(batch, { opacity: 0, y: 20 }),
onEnterBack: batch => gsap.to(batch, { opacity: 1, y: 0 }),
onLeaveBack: batch => gsap.to(batch, { opacity: 0, y: -20 })
});
よく使われるパターン
スクロール時に表示
gsap.utils.toArray('.reveal').forEach(elem => {
gsap.from(elem, {
opacity: 0,
y: 50,
duration: 0.8,
scrollTrigger: {
trigger: elem,
start: 'top 80%',
toggleActions: 'play none none none'
}
});
});
進行状況インジケーター
gsap.to('.progress-bar', {
scaleX: 1,
transformOrigin: 'left center',
ease: 'none',
scrollTrigger: {
trigger: 'body',
start: 'top top',
end: 'bottom bottom',
scrub: 0.3
}
});
スティッキーヘッダーの変形
ScrollTrigger.create({
start: 'top -80',
onUpdate: (self) => {
if (self.direction === 1) {
gsap.to('.header', { y: -80, duration: 0.3 });
} else {
gsap.to('.header', { y: 0, duration: 0.3 });
}
}
});
時間的な崩壊パターン
カウントダウンのスクロール表示
// Reveal countdown sections as user scrolls
const sections = ['days', 'hours', 'minutes', 'seconds'];
sections.forEach((section, i) => {
gsap.from(`.countdown-${section}`, {
opacity: 0,
scale: 0.8,
y: 50,
duration: 0.8,
ease: 'power3.out',
scrollTrigger: {
trigger: `.countdown-${section}`,
start: 'top 80%',
toggleActions: 'play none none none'
}
});
});
スクロールに基づく時間の遅延効果
gsap.timeline({
scrollTrigger: {
trigger: '.time-section',
start: 'top center',
end: 'bottom center',
scrub: 1
}
})
.to('.time-digit', {
textShadow: '0 0 50px #00F5FF, 0 0 100px #00F5FF',
scale: 1.1
})
.to('.particles', {
opacity: 1,
filter: 'blur(0px)'
}, '<');
パフォーマンスのヒント
// Disable on mobile if needed
ScrollTrigger.matchMedia({
'(min-width: 768px)': function() {
// Desktop animations
},
'(max-width: 767px)': function() {
// Simpler mobile animations
}
});
// Refresh on resize
ScrollTrigger.refresh();
// Kill all ScrollTriggers
ScrollTrigger.killAll();
// Kill specific trigger
const st = ScrollTrigger.create({ ... });
st.kill();
リファレンス
- アニメーションの基本については
gsap-fundamentalsを参照してください - タイムラインの構成については
gsap-sequencingを参照してください - ScrollTrigger の React 連携については
gsap-reactを参照してください
コメント
Markdown 対応