【GSAP】横スクロール内で要素を動かす!containerAnimation の使い方
以前の記事で、GSAPの ScrollTrigger を使った横スクロールアニメーションをご紹介しました。今回はその応用編として、「横スクロールしている最中に、画面内に入ってきた要素をアニメーションさせる方法」を解説します!
関連記事
【GSAP】ScrollTriggerで実装する、モダンな「横スクロール」アニメーション
通常の縦スクロールとは違い、横移動の中で発火させるには containerAnimation というプロパティを使います。これを設定することで、トリガーの判定基準が「上下(top/bottom)」から「左右(left/right)」に切り替わるのが最大のポイントです。 シンプルなデモで仕組みを確認していきましょう!
デモ動作
See the Pen GSAP:横スクロール内でアニメーションを発火させる方法 by mikanbako (@mikanbako) on CodePen.
demo: GSAPの横スクロール内でアニメーションを発火させる方法
実装コード紹介
【HTML】
<!-- スクロール用の上の余白 -->
<div class="l-spacer">
<p>↓ スクロールしてね ↓</p>
</div>
<!-- 横スクロールさせたい親要素 -->
<div class="p-scroll-wrap js-scroll-wrap">
<!-- 実際に横に動くコンテナ -->
<div class="p-scroll-container js-scroll-container">
<section class="p-scroll-panel">
<p>画面左から20%の位置に来た時発火</p>
<div class="c-box js-box-1">Box 1</div>
</section>
<section class="p-scroll-panel">
<p>画面の中央に来た時発火</p>
<div class="c-box js-box-2">Box 2</div>
</section>
<section class="p-scroll-panel">
<p>画面左から80%の位置に来た時発火</p>
<div class="c-box js-box-3">Box 3</div>
</section>
</div>
</div>
<!-- スクロール用の下の余白 -->
<div class="l-spacer">
<p>↑ 横スクロール終わり ↑</p>
</div>
【CSS】
/* 前後のスクロール余白用 */
.l-spacer {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
font-weight: bold;
color: #3e3e3e;
}
/* 横スクロールエリアの親(はみ出した部分を隠す) */
.p-scroll-wrap {
overflow: hidden;
}
/* パネルを横並びにするコンテナ */
.p-scroll-container {
display: flex;
width: max-content;
}
/* 各パネルのデザイン */
.p-scroll-panel {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 32px;
font-weight: bold;
color: #fff;
}
/* パネルごとの色分け */
.p-scroll-panel:nth-child(1) { background-color: #1bb4d4; }
.p-scroll-panel:nth-child(2) { background-color: #fce621; color: #3e3e3e; }
.p-scroll-panel:nth-child(3) { background-color: #c72c4c; }
/* アニメーションさせる要素 */
.c-box {
display: flex;
align-items: center;
justify-content: center;
width: 100px;
height: 100px;
margin-top: 20px;
color: #fff;
font-size: 20px;
font-weight: bold;
border-radius: 12px;
background-color: #e83e8c;
}
【JavaScript】
// ScrollTriggerプラグインを登録する
gsap.registerPlugin(ScrollTrigger);
// 要素の取得
const wrap = document.querySelector('.js-scroll-wrap');
const container = document.querySelector('.js-scroll-container');
// 💡 1. 横スクロール自体のTweenを作成し、変数に格納する
const scrollTween = gsap.to(container, {
x: () => -(container.clientWidth - window.innerWidth),
ease: "none",
scrollTrigger: {
trigger: wrap,
pin: true,
scrub: 1,
start: "top top",
end: () => "+=" + (container.clientWidth - window.innerWidth),
invalidateOnRefresh: true
}
});
// 💡 2. 各パネルのアニメーションを個別に設定
// 【Box 1】発火:left 20% (要素の左端が、画面左から20%の位置に来た時)
// 動き:下からフワッと浮き上がる
gsap.from('.js-box-1', {
y: 100,
autoAlpha: 0,
duration: 1,
scrollTrigger: {
trigger: '.js-box-1',
containerAnimation: scrollTween, // 横スクロールと連動させる
start: "left 20%",
toggleActions: "play none none reverse"
}
});
// 【Box 2】発火:center center (要素の中央が、画面の中央に来た時)
// 動き:くるっと回転しながら現れる
gsap.from('.js-box-2', {
rotation: 360,
scale: 0,
duration: 1,
scrollTrigger: {
trigger: '.js-box-2',
containerAnimation: scrollTween, // 横スクロールと連動させる
start: "center center",
toggleActions: "play none none reverse"
}
});
// 【Box 3】発火:right 80% (要素の右端が、画面左から80%の位置に来た時)
// 動き:横にビヨーンと伸びてから戻る(弾むようなバネの動き)
gsap.from('.js-box-3', {
scaleX: 0,
transformOrigin: "left center",
duration: 1,
ease: "elastic.out(1, 0.3)",
scrollTrigger: {
trigger: '.js-box-3',
containerAnimation: scrollTween, // 横スクロールと連動させる
start: "right 80%",
toggleActions: "play none none reverse"
}
});
コード解説
containerAnimation の指定
// 💡 1. 横スクロール自体のTweenを作成し、変数に格納する
const scrollTween = gsap.to(container, {
x: () => -(container.clientWidth - window.innerWidth),
ease: "none",
scrollTrigger: {
trigger: wrap,
pin: true,
scrub: 1,
start: "top top",
end: () => "+=" + (container.clientWidth - window.innerWidth),
invalidateOnRefresh: true
}
});
// 💡 2. 各パネルのアニメーションを個別に設定
gsap.from('.js-box-1', {
...
scrollTrigger: {
...
containerAnimation: scrollTween, // 横スクロールと連動させる
...
}
});
横スクロールを動かしているアニメーション(今回の場合は scrollTween)を、各要素の ScrollTrigger に紐づけます。これにより、「親の横移動」を基準にして発火タイミングを計算してくれます。
start の方向が変わる
// 【Box 1】発火:left 20% (要素の左端が、画面左から20%の位置に来た時)
gsap.from('.js-box-1', {
...
scrollTrigger: {
...
containerAnimation: scrollTween,
start: "left 20%",
...
}
});
通常の縦スクロールでは start: "top center"(要素の上が画面中央にきたら)のように指定しますが、横移動の場合は start: "left center"(要素の左端が画面中央にきたら) のように、left や right を使ってX方向の判定を行います!
各トリガー(start)の違いに注目!
start: "left 20%"(Box 1)
要素の「左端(left)」が画面の「左から20%の位置」に来た時に動きます。遅めの発火アニメーションです。
start: "center center"(Box 2)
要素の「中央」が画面の「中央」に来た時に動きます。画面のど真ん中でアニメーションさせたい時に使います。
start: "right 80%"(Box 3)
要素の「右端(right)」が画面の「左から80%の位置」に来た時に動きます。早くアニメーションを見せたい時に使います!
補足:公式ドキュメント
より詳しい仕様や最新の対応状況については、以下の公式ドキュメントをご参照ください。
まとめ
今回はScrollTrigger を使った横スクロールアニメーションの応用編として、「横スクロールしている最中に、画面内に入ってきた要素をアニメーションさせる方法」を解説しました!
この横スクロール+出現アニメーションの組み合わせは頻繁に使われます。応用が効くテクニックなので、ぜひマスターしてみてください!