スクロールで物語る(Scroll Storytelling)
このページでは、GSAPのScrollTriggerで実装するscrub・pin・横スクロール・パララックスなど、スクロールに連動した高度なアニメーションパターンをデモとコードで確認できます。
↓ 下にスクロールして6つのデモを体験してください。各セクションのコードは下部で確認できます。
読み込み中...
各デモのコード解説
各デモをクリックして実装コードを確認してください。すべてのデモは useGSAP({ scope: containerRef }) でスコープを設定し、アンマウント時に自動クリーンアップされます。
進捗バー(scrub)
スクロール量に連動して左から右へ伸びるプログレスバー。scrub: true でスクロール位置に即時追従します。
gsap.to('.progress-bar', {
scaleX: 1,
ease: 'none',
scrollTrigger: {
trigger: containerRef.current, // スクロール対象の要素
start: 'top top', // 要素の上端がビューポート上端に来たとき開始
end: 'bottom bottom', // 要素の下端がビューポート下端に来たとき終了
scrub: true, // スクロール量に連動(trueで即時追従)
},
});
// HTML: origin-left で左から伸びるようにする
// <div class="progress-bar h-1 bg-pink-400 origin-left" style={{ transform: 'scaleX(0)' }} />テキスト演出(scrub)
複数行のテキストが1行ずつスクロールに連動してフェードイン。gsap.utils.toArray で一括設定できます。
// gsap.utils.toArray で複数要素を取得してまとめて設定
gsap.utils.toArray<HTMLElement>('.text-line').forEach((line) => {
gsap.from(line, {
opacity: 0,
y: 40,
scrollTrigger: {
trigger: line,
start: 'top 80%', // 要素の上端がビューポートの80%位置に来たとき
end: 'top 50%', // 要素の上端がビューポートの50%位置に来たとき
scrub: 1, // 数値指定でなめらかな追従(秒単位の遅延)
},
});
});
// HTML: 初期状態を opacity: 0 にしておくとフラッシュを防げる
// <p class="text-line" style={{ opacity: 0 }}>テキスト</p>画像ズーム(scrub)
スクロールに連動して画像が scale: 1 → 1.3 にゆっくりズーム。overflow: hidden で拡大をクリップします。
gsap.to('.zoom-inner', {
scale: 1.3,
ease: 'none',
scrollTrigger: {
trigger: '.zoom-section',
start: 'top bottom', // セクションがビューポート下端に入ったとき開始
end: 'bottom top', // セクションがビューポート上端を超えたとき終了
scrub: true,
},
});
// HTML: overflow: hidden で拡大した部分をクリップ
// <section class="zoom-section overflow-hidden">
// <div class="zoom-inner min-h-screen" style={{ background: 'linear-gradient(...)' }} />
// </section>パララックス
背景が前景より遅い速度で動くパララックス効果。yPercent で要素を縦方向に移動させます。
gsap.to('.parallax-bg', {
yPercent: -30, // 自身の高さの30%分だけ上に移動(ページより遅い速度)
ease: 'none',
scrollTrigger: {
trigger: '.parallax-section',
start: 'top bottom',
end: 'bottom top',
scrub: true,
},
});
// HTML: 背景を150%の高さにして余白を持たせる
// <section class="parallax-section overflow-hidden relative">
// <div
// class="parallax-bg absolute inset-x-0"
// style={{ height: '150%', top: '-25%', background: 'linear-gradient(...)' }}
// />
// <div class="relative z-10">前景コンテンツ</div>
// </section>ピン留めコンテンツ切り替え(pin)
セクションをピン留めした状態で、スクロールに連動して中のスライドが順番に切り替わります。
const slides = gsap.utils.toArray<HTMLElement>('.pin-slide');
const tl = gsap.timeline({
scrollTrigger: {
trigger: '.pin-section',
pin: true, // セクションをピン留め(固定)
start: 'top top',
end: `+=${slides.length * 400}`, // スライド数 × 400px のスクロール距離
scrub: 1,
},
});
// スライドを順番にフェード切り替え
slides.forEach((slide, i) => {
if (i > 0) {
tl.from(slide, { autoAlpha: 0, y: 30, duration: 1 });
tl.to(slides[i - 1], { autoAlpha: 0, y: -30, duration: 1 }, '<');
}
});
// autoAlpha は opacity と visibility をまとめて制御するGSAPの特殊プロパティ横スクロール演出(pin)
縦スクロールを横移動に変換。セクションをピン留めしてカードを横に流します。
const cards = gsap.utils.toArray<HTMLElement>('.h-card');
const cardWidth = cards[0].offsetWidth; // 各カードの幅を取得
gsap.to('.h-track', {
x: -(cards.length - 1) * cardWidth, // カード(n-1)枚分だけ左に移動
ease: 'none',
scrollTrigger: {
trigger: '.horizontal-section',
pin: true, // セクションをピン留め
scrub: 1,
end: () => `+=${(cards.length - 1) * cardWidth}`, // スクロール距離を動的計算
},
});
// HTML: overflow: hidden でスクロールバーを隠す
// <section class="horizontal-section overflow-hidden">
// <div class="h-track flex" style={{ width: `${cards.length * 100}%` }}>
// {cards.map(card => (
// <div class="h-card flex-shrink-0" style={{ width: `${100 / cards.length}%` }}>
// {card.label}
// </div>
// ))}
// </div>
// </section>GSAP ScrollTrigger のポイント
- •
gsap.registerPlugin(ScrollTrigger, useGSAP)はコンポーネント外(モジュールレベル)で一度だけ呼ぶ - •
scrub: trueはスクロールに即時追従。scrub: 1は1秒の遅延でなめらかに追従 - •
pin: trueでセクションをピン留め。スクロールしても要素が固定され、endに到達すると解除 - •
start / endは"top top"のように「要素の位置 ビューポートの位置」で指定。"+= 400"はピクセル数での相対指定 - •
useGSAP({ scope: containerRef } )でクリーンアップを自動化。アンマウント時にScrollTriggerも破棄される - •
autoAlphaは GSAP 独自のプロパティでopacityとvisibilityを連動させる
同じカテゴリの他のページ
文字を演出する(Text Animation)| UI Memo
GSAPのSplitText・ScrambleTextで実装する文字アニメーションのサンプル。1文字ずつフェード・スライド・波・スクランブル・バラけて再集合など、テキスト演出のUIパターン実例集。
動きの質感を選ぶ(Easing)
イージングの違いを体験で比較。power・back・bounce・elasticなどGSAP・Framer Motion・CSS Transitionのeaseを一覧・比較できるUIパターン実例集。
スクロールで見せる(Scroll Reveal)
スクロールで見せるアニメーションのサンプル。whileInView・IntersectionObserverを使ったUIパターン実例集。Framer MotionとIntersection Observer APIで実装比較。