GSAPでスナップする横スクロールを作ってみた!

フロントエンド
エンジニア

カトリーヌ

こんにちは、カトリーヌです。

フロントエンド
エンジニア

カトリーヌ

サイトの途中で一部のセクションが横スクロールになるのってスタイリッシュでカッコいいですよね!
縦スクロールに連動して横に動くもの

こういうの

縦スクロールしたら横にスクロールする

でもスクロールするのが面倒だったり、自分の知りたい情報が画面に収まらない!

などちょっとストレスに感じる人もいるかと思います。

そこで、少しのスクロールでスナップするようにできる横スクロールを作成します!

完成したコード

まず基本となる縦スクロールすると横にスクロールされるを作成する必要があるのですが・・・・
それを簡単に叶えてくれるのがGSAPです。
JavaScriptライブラリで複雑なアニメーションも簡単に実装することができます。

そんなGSAPを使用して作ったのがこちらです。

See the Pen
Untitled
by ikura (@ikuradonburi)
on CodePen.

GSAPについて

ライセンス

GSAPは2つのライセンスがあり

Standard(標準ライセンス):無料
Business(商用ライセンス):有料

GSAPはある特定の条件の場合は、GreenSockの有料ライセンスが必要とあります。

ユーザーがそのサイトを利用する時にお金を払う必要がある場合

例)NetFlixなど – GSAPを使用した有料会員専用エリアのあるECサイト

とのことなので通常のWEBサイトであれば無料で使用できます!

上記の他にライセンスが必要となる例があるのでご確認ください

Licensing

インストール

GSAPは下記からインストールできます。

Installation | GSAP | Docs & Learning

読み込みコードも書いてあるのですぐ導入ができます。

また、今回はスクロールによって要素を変化させるので「ScrollTrigger」もチェックを入れて
出力されたコードを各々の形式で読み込みます。

コードの説明

ここからは、コードを説明していきます。

初期設定

プラグインの登録と使用するアイテムを変数に格納します。

gsap.registerPlugin(ScrollTrigger);
let slides = gsap.utils.toArray("[data-item]");
const wrapper = document.querySelector("[data-wrapper]");
const wrapperHeight = wrapper.offsetHeight;

gsap特有のオブジェクト・メソッドを使用します。
gsap.registerPlugin();:インストール時にチェックしたプラグインを読み込む
gsap.utils.toArray();:スクロールによって効果を付与したいターゲットアイテム全てを配列として取得

横スクロール実装

GSAPの基本の形となり、なんとこれだけで動きます

    gsap.to(slides, {
      x: 100,
    });

ここからプロパティを追加して色んなアニメーションを実装していく形になります。
では、基本的な横スクロールを実装します。

See the Pen
Untitled
by ikura (@ikuradonburi)
on CodePen.

gsap.to(slides, { //[data-item] → アニメーションさせる要素
  xPercent: -100 * (slides.length - 1), //移動の方向:数値がマイナスなので左に100%X軸方向に移動
  ease: "none", //アニメーションのイージング設定:なし
  scrollTrigger: {
    trigger: wrapper, //アニメーション開始要素の指定
    pin: true, //要素を固定
    scrub: 1, //スクロール量に合わせたアニメーションで数値が大きいほど遅くなる
    start: "top top", //ScrollTriggerの開始位置を指定
    end: `+=${wrapperWidth}`, //ScrollTriggerの終了位置を指定 
  },
});

これで縦スクロールに連動して横にスクロールする要素が完成しました。

次は、このコードをもう少し変更して1要素ごとスナップさせます。

スナップさせる

スナップさせるにはScrollTriggerのsnapを使用します。

        snap: {
          snapTo: 1 / (slides.length - 1), //要素を均等な位置でスナップさせる
          duration: {min: 0.3, max: 0.7}, //スナップアニメーションの長さ
          delay: 0.1, //アニメーションが開始されるまでの時間
          ease: "none", //アニメーションのイージング設定:なし
        },

表示用クラスの付与

上記を設定することで一枚ずつスナップされるようになりました。

個人的に画面に表示されている要素以外は非表示にしたいので、カレント要素のみis-showを追加するようにします

        onUpdate: function (self) { // スクロール位置に応じて処理を行う
          var progress = self.progress; // 進行状況を取得
          var currentIndex = Math.round(progress * (slides.length - 1)); // 現在のスライドを取得

          slides.forEach(function (slide, index) { // 任意のクラスを付与
            if (index === currentIndex) {
              slide.classList.add("is-show");
            } else {
              slide.classList.remove("is-show");
            }
          });
        },

onUpdateは、1要素進むごとにイベントが発火します

最後に

いかがでしたでしょうか?

これで縦スクロールに連動して横スクロールされるコードが完成しました。

今回は横スクロールのみですが、GSAPでは色んなプロパティを組み合わせて
複雑なアニメーションを実装できるので
色々試してみてください〜!

ところで

ロジカルスタジオでは、フロントエンドエンジニアを募集しております!

下記リンクからお待ちしております!