📝 はじめに
この実装は、joebentaylor1995/infinite-scroll-with-parallax の Lenis + GSAP による無限スクロール表現を、記事内で試しやすい React コンポーネントへ置き換えたものです。元のデモは Lenis の infinite: true と ScrollTrigger.scrollerProxy() で滑らかな循環を作っていますが、ここでは依存を増やさず、同じスライド群を3セット並べて中央セットへ戻すことで終端を隠しています。
画像は通常のスクロール量より大きめの高さで敷き、yPercent: -18 から 18 へ動かしています。セクション自体は一画面ずつ進むのに、画像だけが少し遅れて抜けていくため、ギャラリーの切り替わりに奥行きと余韻が生まれます。
🛠️ 実装のポイント
- スクロール領域をコンポーネント内に閉じる
.loop-scrollerにheight: 100svhとoverflow-y: autoを与え、ページ全体ではなくデモ内だけでスクロールを完結させています。これにより、記事ページの通常スクロールと干渉しにくく、ScrollTrigger 側もscrollerにこの要素を渡すだけで管理できます。 - 3セット複製して中央セットへ戻す
slidesを3回複製し、初期表示を真ん中のセットへ移動します。スクロール位置が上端側または下端側へ近づいたら、同じ見た目の位置へcycleHeight分だけ戻すため、ユーザーには連続したスクロールとして見えます。 - React生命周期におけるコンテキスト管理
gsap.context()の中で ScrollTrigger、resize、scroll イベントをまとめ、返り値でイベントリスナーを外しています。最後にcontext.revert()を呼ぶことで、コンポーネントのアンマウント時に GSAP のインラインスタイルや ScrollTrigger もまとめて破棄できます。
💡 使いどころとカスタマイズ
- 最適なユースケース: 写真家や建築、ファッション、ホテル、イベント告知など、ビジュアルを大きく見せながら「まだ続く」感覚を作りたいギャラリーに向いています。
- 調整ダイヤル(パラメーター変更のヒント):
yPercentを-10/10に変更すると、視差が弱まり、落ち着いたギャラリーになります。cycleHeight * 0.5とcycleHeight * 1.5を0.35/1.65に寄せると、ループ補正のタイミングが端に近づき、長くスクロールできる感覚になります。