JavaScript
GSAPで、縦スクロールで横に動く(横スクロール)アニメーションをパララックス(慣性付)で
操作としては縦にスクロールさせているのに、動作としては横に動くようにする方法をご紹介します。GSAPというライブラリを用いた方法です。
部分的にそのような演出を施すと、サイトにメリハリがつけられます。
GSAPとは?
GSAPはウェブサイトに趣向を凝らしたアニメーションを実装することができるJavaScriptのライブラリです。
GSAPが用意しているものには、CSSのアニメーションプロパティで実現できることも多いのですが、縦にスクロールさせているのに横に動作するというアニメーションを実装する際にはGSAPのライブラリの一つである「ScrollTrigger」が便利です。ページスクロールをトリガーとして、設定したタイミングで指定のアニメーションが実行できます。
ここでは、GSAPのライブラリ「ScrollTrigger」を使った横スクロールアニメーションの実装方法をご紹介します。
縦スクロールで横に動かす実装内容のデモ
次のように、縦スクロールしてある地点に到達すると、その地点で縦スクロールが止まり、縦スクロールの動作に応じて一定の距離横スクロールするという実装をする方法をご紹介します。
See the Pen Untitled by Takahiro Inada (@tkhr1) on CodePen.
GSAPの利用方法
まずはGSAPを利用する方法です。
CDNを利用する場合
CDNを利用する場合は次の2つを読み込みます。
1つ目が基本的なプログラムで、2つ目はここでご紹介する横スクロールアニメーションを実装するために必要なプログラムです。
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.3/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.3/ScrollTrigger.min.js"></script>
最新バージョンはこちらで確認してください。
npmの場合
コマンド
npm i gsap
JavaScript
import gsap from 'gsap';
ダウンロードして読み込む場合
次のページからダウンロードします。
GSAP Installation
ダウンロードしたファイルから以下2つのファイルを読み込みます。CDNのところで説明したのと同じで、1つ目が基本的なプログラムで、2つ目はここでご紹介する横スクロールアニメーションを実装するために必要なプログラムです。
<script src="./umd/gsap.js"></script>
<script src="./umd/ScrollTrigger.js"></script>
縦スクロールで横に動かす実装のコード
次にコードです。
HTML
<div class="box-01">
<p>↓スクロールしてください。</p>
</div>
<div class="box-02">
<div class="slides-wrapper">
<div class="slide"><img class="slide-img" src="画像ファイルの場所" alt=""></div>
<div class="slide"><img class="slide-img" src="画像ファイルの場所" alt=""></div>
<div class="slide"><img class="slide-img" src="画像ファイルの場所" alt=""></div>
<div class="slide"><img class="slide-img" src="画像ファイルの場所" alt=""></div>
<div class="slide"><img class="slide-img" src="画像ファイルの場所" alt=""></div>
</div>
</div>
<div class="box-03"></div>
横スクロールさせる要素の外枠は2つの要素(ここで言う.box-02
と.slides-wrapper
)で囲います。
CSS
.box-01,
.box-03{
width: 100%;
height: 100vh;
background-color: #333;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
}
.box-02{
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.slides-wrapper{
display: flex;
gap: 30px;
width: calc(100% - 50px);
margin: 0 auto;
overflow: hidden;
}
.slide-img{
width: 50vw;
height: 50vh;
object-fit: cover;
}
横スクロールさせる要素の高さはそれらしく動かすうえで条件があるので、色々試してみてください。理由としては、次のJavaScriptのところで説明するdiv.pin-spacerがHTMLに足されるというところにありますので、そのことを把握したうえで試すと、理屈が分かってくると思います。
JavaScript
const container = document.querySelector('.box-02');
const slides = document.querySelectorAll('.slide');
const containerWidth = container.offsetWidth;
gsap.to( slides, { // slidesに対して以下のアニメーションを設定
xPercent: -110 * (slides.length - 1), // 横に動く方向と距離(この例は右側にスライドの合計幅より少し横スクロール)
ease: "none", //アニメーションの種類をnoneにする
scrollTrigger: {
trigger: container, //containerに到達したら発火
pin: true, // ピン留をtrueにすることでcontainerの縦スクロールが止まる
scrub: 1, //スクロール当たりのアニメーションが動く時間
end: () => "+=" + containerWidth, // 横スクロールが終わる地点
anticipatePin: 1, // ピン留のタイミング
invalidateOnRefresh: true, // リサイズ時の調整でtrueにしておく
}
})
gsap.to()
メソッドは、gsap( 第一引数, 第二引数 )
とすることで第一引数を対象として、第二引数で指定した内容でアニメーションを実行します。
ここの例で言うと、第一引数がdocument.querySelectorAll('.slide')
で取得された変数slides
で、そのslides
に対して{}
内のgsapのプロパティで指定したアニメーションが動くということです。trigger
はgsapが発火する地点を決めます。なお、start
でそのエリア内の発火を座標で指定することができますが、この例のように省略した場合はデフォルト値であるstart: 'top top'
、つまり対象エリア内の左上となります。pin
をtrue
にすることで、trigger
で指定したエリア(ここで言うcontainer
)内の縦スクロールの動きを止めることができます。
また、pin
をture
にすることで、trigger
で指定したエリアの外側にはdiv.pin-spacer
が追加されます。div.pin-spacer
にはGSAPにより自動で付けられるCSSがありますので、その値を確認すると理屈の理解が進むと思います。scrub
はスクロール当たりのアニメーションが動く時間を決めるもので、0.3~0.5
だと普通の動きになり、1
にすることで慣性のある動きになります。anticipatePin
は、ピン留の遅延を防ぐための調整で、基本的には1が推奨です。もし1で遅延する場合は少し値を変えてみるなどするようなものです。invalidateOnRefresh
は、リサイズによりスクロール値が再計算される場合に、内部で記録されている値をリセットさせることで正しくアニメーションが動くようにするものです。true
にしておきます。
横スクロールアニメーションのメリット
冒頭でも述べましたが、通常、縦スクロールするはずの操作で横スクロールすると、不思議な感覚になります。つまり特別な感覚をユーザーに与えることができて、他のサイトとの差別化に繋がると言えます。
他に横スクロールさせるUIとしてカルーセルスライダーがありますが、そちらは自動またはドラッグ/スワイプの操作で横に動かすというものになります。カルーセルスライダーは直感的で心地よい操作を提供するメリットがありますが、不思議な感覚というのはないのと、ユーザーが横スクロールさせずにそのまま縦スクロールさせてしまい、見てもらえない可能性が高いというデメリットがあります。
一方で本記事でご紹介したUIの場合、縦スクロールしたつもりが横に流れるので、カルーセルスライダーに比べて見てもらいやすいというメリットがあります。
横スクロールアニメーションのデメリット
本UIのデメリットとしては、操作が直感的ではないということ、必ずしも見たい部分ではない場合にも、下部に表示されている部分を飛ばしてみるということができず、ユーザーは横スクロールが終わるまでスクロールし続けなくてはいけないということがあります。
そのため、ユーザーが何度か訪れることが想定されるようなページで上部に配置してしまうと煩わしく感じられてしまうので、そうならないように留意することが望ましいと言えます。
CSSだけで横スクロールアニメーションの実装をする方法「Scroll-driven Animations」について
2023年7月にアップデートされたChrome115以降では、Scroll-driven Animationsという仕様がサポートされ、スクロールに連動したアニメーションがCSSだけで実装できるようになりました。
まだSafariがサポートしてないので、実案件では用いることが現実的ではない状況ですが、こちらの記事で詳しく解説していますので、よろしければご参照ください。
CSSだけでスクロールアニメーション!Scroll-driven Animations、animation-timelineプロパティを解説
なお、Scroll-driven Animationsの仕様は次のページで、まだ草案(draft)の状態です。
Scroll-driven Animations |W3C Working Draft, 6 June 2023
まとめ
GSAPはこのように、縦スクロールをピン留して横スクロールさせるという演出を施すのに便利なライブラリです。ぜひお試しください。