通常スクロールというのは上下にするので画面が縦に移動しますが、GSAPを使って上下にスクロールしながら横にスクロールさせることができます。
今回はGSAPを使った方法を解説するので、GSAPを使ったことがないという人は以下の記事を参照下さい。
GSAPとは?基本的な使い方とアニメーションのサンプル付きで解説
続きを見る
重要なコード以外は省略している箇所が多いので、全部見たい人はCodePen左上のHTML・CSS・JSをクリックして下さい。
(有料になっていたらすいません🙇♂️)
GSAPで横スクロールをScrollTriggerで作る方法
今回はGSAPで横スクロールさせますが、GSAPのプラグイン『ScrollTrigger』も使います。
ScrollTriggerの使い方はこちらの記事を参照下さい。
【GSAP】ScrollTriggerの使い方とスクロールアニメーションのサンプルを紹介
続きを見る
画面全体を横スクロール
まずは画面全体を横スクロールさせてみます。
コードはこちらです。
<div class="wrapper js-wrapper">
<div class="side-scroll side-scroll-01 js-scroll">
<p>スライド 1/5</p>
</div>
<div class="side-scroll side-scroll-02 js-scroll">
<p>スライド 2/5</p>
</div>
<div class="side-scroll side-scroll-03 js-scroll">
<p>スライド 3/5</p>
</div>
<div class="side-scroll side-scroll-04 js-scroll">
<p>スライド 4/5</p>
</div>
<div class="side-scroll side-scroll-05 js-scroll">
<p>スライド 5/5</p>
</div>
</div>
CSSは重要なもの以外は省略します。
.wrapper {
display: flex; /* 要素を横並び */
height: 100vh; /* 要素の高さを画面いっぱい */
width: 500%; /* 要素の数×100% */
}
.side-scroll-01 {
background-image: url(“画像パス1”);
}
.side-scroll-02 {
background-image: url("画像パス2”);
}
.side-scroll-03 {
background-image: url("画像パス3”);
}
.side-scroll-04 {
background-image: url("画像パス4”);
}
.side-scroll-05 {
background-image: url("画像パス5”);
}
CSSで重要なのはwidth: 500%;
で、これは要素の数×100%になります。
そして重要なのがJavaScriptです。
const wrapper = document.querySelector(".js-wrapper");
if (wrapper) {
const slides = gsap.utils.toArray(".js-scroll");
const wrapperWidth = wrapper.offsetWidth;
// 横スクロールアニメーションの設定
gsap.to(slides, {
xPercent: -100 * (slides.length - 1), // -X軸方向に移動
ease: "none", // アニメーションのイージング(noneは定速)
scrollTrigger: {
trigger: wrapper, // アニメーション開始のトリガー要素
pin: true, // 要素を固定
scrub: 1, // スクロール量に合わせてアニメーション
end: `+=${wrapperWidth}`, // アニメーションが終わる位置
},
});
}
JavaScriptは1行ずつ解説を補足します。
const slides = gsap.utils.toArray(".js-scroll");
:.js-scroll
のclassを持つ要素を取得して配列に格納。const wrapperWidth = wrapper.offsetWidth;
:要素の幅を取得。xPercent: -100
:要素を100%X軸方向に移動。数値がマイナスなので左方向。slides.length - 1
:要素数から最後の要素を除く(最初の要素は0番目と数えるため)xPercent: -100 * (slides.length - 1)
:最初の要素(スライド)が表示された状態から最後の要素まで移動するアニメーションの設定。要素が追加・削除されて数が変わっても問題なし。ease: "none"
:イージングなし(定速)trigger: wrapper
:アニメーション開始のトリガー要素。pin: true
:要素を固定。今回は画面全体を固定して横並びにした要素がスクロールに応じて流れる。scrub: 1
:スクロール量に合わせてアニメーション。trueだと有効になるだけで、数値だと数値が大きいほど遅く動く。end: `+=${wrapperWidth}`
:アニメーションがwrapperWidth
の分だけ右に移動して終了、つまり要素の固定解除される。
サンプルがこちらです。
See the Pen
GSAP(横スクロール・全画面) by junpei (@junpei-sugiyama)
on CodePen.
画面全体を横スクロール(スナップあり)
先ほどはスクロールを途中で止めたらスライドも止まりましたが、今度はスクロールを途中で止めたら表示しているスライドの最後まで自動で移動するようにします。
具体的にはJavaScriptでsnap
を追記します。
const wrapper = document.querySelector(".js-wrapper");
if (wrapper) {
const slides = gsap.utils.toArray(".js-scroll");
const wrapperWidth = wrapper.offsetWidth;
// 横スクロールアニメーションの設定
gsap.to(slides, {
xPercent: -100 * (slides.length - 1), // -X軸方向に移動
ease: "none", // アニメーションのイージング(noneは定速)
scrollTrigger: {
trigger: wrapper, // アニメーション開始のトリガー要素
pin: true, // 要素を固定
scrub: 1, // スクロール量に合わせてアニメーション
snap: {
// スナップスクロールの設定
snapTo: 1 / (slides.length - 1), // スナップで移動する位置
duration: { min: 0.2, max: 0.6 }, // スナップで移動する遅延時間
ease: "none", // アニメーションのイージング(noneは定速)
},
end: `+=${wrapperWidth}`, // アニメーションが終わる位置
},
});
}
追記したコードを解説します。
snap
:スナップスクロールの設定を格納するオブジェクト。snapTo: 1 / (slides.length - 1)
:スクロール時に要素を均等な位置でスナップさせる。duration: { min: 0.2, max: 0.6 }
:スナップスクロール時の最小の移動時間と最大の移動時間。スクロールの位置に応じて移動時間は変わる。
こちらがサンプルです。
スライドを途中で止めたら、途中まで表示しているスライドの最後まで自動でスクロールします。
See the Pen
Untitled by junpei (@junpei-sugiyama)
on CodePen.
途中から横スクロール
先ほどまでは全画面でしたが、今度は途中から横スクロールさせたいと思います。
コードは横スクロールに関するところだけ書きます。
<div class="side-scroll js-wrapper">
<div class="side-scroll-container">
<ul class="side-scroll-list">
<li class="side-scroll-item js-scroll">
<img src="画像パス1" alt="" />
</li>
<li class="side-scroll-item js-scroll">
<img src="画像パス2" alt="" />
</li>
<li class="side-scroll-item js-scroll">
<img src="画像パス3" alt="" />
</li>
・・・
</ul>
</div>
</div>
CSSはほぼ調整用なので割愛します(サンプル左上のCSSをクリックすれば確認できます)
そして重要なJavaScriptはこちらです。
// コンテナ要素とスライド要素を取得
const wrapper = document.querySelector(".js-wrapper");
const slides = gsap.utils.toArray(".js-scroll");
// コンテナの幅を取得
const wrapperWidth = wrapper.offsetWidth;
// 横スクロールアニメーションの設定
gsap.to(slides, {
xPercent: -100 * (slides.length - 1), // -X軸方向に移動
ease: "none", // アニメーションのイージング(noneは定速)
scrollTrigger: {
trigger: wrapper, // アニメーション開始のトリガー要素
pin: true, // 要素を固定
scrub: 1, // スクロール量に合わせてアニメーション
start: "top top", // アニメーションが始まる位置
end: `+=${wrapperWidth}`, // アニメーションが終わる位置
anticipatePin: 1, // ピン留めアニメーションをスムーズに開始
invalidateOnRefresh: true, // ページの再読み込み時(リサイズ時)に値を再計算する
},
});
先ほどと同じコードが多いですが、3点補足します。
start: "top top"
:スクロールさせる要素のセクション上部が画面上部に到達したらアニメーション開始。start: "要素の位置 画面の位置"
です。anticipatePin: 1
:高速でスクロールした時にpinによるピン留めのズレを防ぐ。初期値は0。invalidateOnRefresh: true
:画面サイズが変化した時に値を再計算する。
こちらがサンプルです。
See the Pen
Untitled by junpei (@junpei-sugiyama)
on CodePen.
横スクロールされる要素はCSSで横幅いっぱいにしたり色々調整は可能です(横並びのdisplay: flex;
以外はなくても横スクロールします)
まとめ
今回はGSAPを使った横スクロールの実装方法を解説してきました。
途中で横スクロールするのは最後までスクロールしないと下にスクロールできないので、ユーザーからしたら不便に感じるかも知れません。
なので使い所には注意しましょう。
以上になります。