【GSAP】スクロール速度で要素を回す!ScrollTriggerの getVelocity() を使ったUI実装

以前の記事で、GSAPの ScrollTrigger を使って「スクロール全体の進捗(progress)」を取得し、プログレスバーを作る方法をご紹介しました。 今回はその応用編として、「スクロールの速度と方向(velocity)」 を取得する方法をご紹介します!

関連記事

ScrollTrigger の getVelocity() メソッドを使うと、「今どれくらいの勢いでスクロールしているか」「上と下、どちらの方向にスクロールしているか」を数値として簡単に取得できます。

今回はこれを利用して、画面右下に固定した要素を「スクロールの勢いに合わせて右回転・左回転させる」という、少し遊び心のあるインタラクティブなUI実装をしてみましょう!

デモ動作

See the Pen ScrollTriggerのvelocityでスクロール速度を取得する by mikanbako (@mikanbako) on CodePen.

全画面でのデモ動作は以下のリンクからご確認下さい!(別タブで開かれます)

実装コード紹介

【HTML】

<!-- スクロールを発生させるための全体ラッパー -->
<div class="l-wrap js-trigger-wrap">
  <h2>ScrollTrigger: getVelocity() デモ</h2>
  <p class="p-desc">上下に激しく、またはゆっくりスクロールしてみてください!<br>右下の要素がスクロール速度に連動して回転します。</p>
  
  <!-- スクロール領域を確保するためのダミーコンテンツ -->
  <div class="p-scroll-space">
    <span>Scroll Down ↓</span>
  </div>
  <div class="p-scroll-space">
    <span>Keep Scrolling ↓</span>
  </div>
  <div class="p-scroll-space">
    <span>Scroll Up ↑</span>
  </div>
</div>

<!-- Velocity値表示用テキスト要素 -->
<div class="c-velocity-value">Velocity: <span class="js-velocity-value"></span></div>

<!-- 画面右下に固定する回転要素 -->
<div class="c-gear js-gear">⚙️</div>

【CSS】

.l-wrap {
  width: 100%;
  padding-top: 40px;
  color: #3e3e3e;
  text-align: center;
}
h2 { 
  margin-bottom: 16px;
  font-size: 16px;
  color: #1bb4d4;
}
.p-desc { 
  margin-bottom: 40px;
  font-size: 16px;
  font-weight: bold;
  color: #666;
  line-height: 1.6;
}

/* スクロール用の余白 */
.p-scroll-space {
  height: 80vh; /* スクロールさせるために高さを出す */
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 32px;
  font-weight: bold;
  color: #ccc;
  border-top: 1px dashed #ddd;
}

/* Velocity値表示用テキスト要素 */
.c-velocity-value {
  position: fixed;
  bottom: 140px;
  right: 40px;
  font-size: 15px;
  color: #ccc;
}

/* 💡 回転させる右下の要素(固定配置) */
.c-gear {
  position: fixed;
  bottom: 40px;
  right: 40px;
  font-size: 60px;
  /* GSAPで動かす際、中心を基準に回転させる設定 */
  transform-origin: center center; 
  z-index: 100;
  /* ※CSSのtransitionは書かない!(GSAPと衝突するため) */
}

【JavaScript】

// プラグインの登録
gsap.registerPlugin(ScrollTrigger);

// Velocity値表示用テキスト要素
const velocityValueText = document.querySelector('.js-velocity-value');

// .l-wrap 全体をトリガーにして設定
ScrollTrigger.create({
  trigger: ".js-trigger-wrap",
  start: "top top",
  end: "bottom bottom",
  onUpdate: (self) => {
    // 1. スクロール速度(velocity)を取得
    // 下スクロール時はプラスの値、上スクロール時はマイナスの値になります
    const velocity = self.getVelocity();

    // 値表示用テキスト更新
    velocityValueText.textContent = Math.round(velocity);

    // 2. 取得した速度を使って要素を回転させる
    gsap.to('.js-gear', {
      // "+=" を使うことで、現在の角度に「速度 × 係数」を足し続ける
      // 0.05は回転具合を調整するための係数です。お好みで変更可能!
      rotation: `+=${velocity * 0.05}`, 
      
      // 滑らかに減速して止まるための設定
      ease: "power2.out", 
      duration: 0.5,
      
      // 連続でスクロールされた時にアニメーションを上書きして自然に繋ぐ
      overwrite: "auto"
    });
  }
});

コードの解説・仕組み

self.getVelocity() が返す値

onUpdate: (self) => {
  // 1. スクロール速度(velocity)を取得
  // 下スクロール時はプラスの値、上スクロール時はマイナスの値になります
  const velocity = self.getVelocity();
  ...

onUpdate 内で取得できる velocity は、ピクセル/秒(px/s)のスクロール速度を表しています。 最大のポイントは、方向によって値の「プラス / マイナス」が変わるという点です!

  • 下へスクロール: プラスの値(例: 1500)
  • 上へスクロール: マイナスの値(例: -1500)

rotation: "+=" で回転を更新させる

// 2. 取得した速度を使って要素を回転させる
gsap.to('.js-gear', {
  // "+=" を使うことで、現在の角度に「速度 × 係数」を足し続ける
  // 0.05は回転具合を調整するための係数です。お好みで変更可能!
  rotation: `+=${velocity * 0.05}`, 
      
  // 滑らかに減速して止まるための設定
  ease: "power2.out", 
  duration: 0.5,
      
  // 連続でスクロールされた時にアニメーションを上書きして自然に繋ぐ
  overwrite: "auto"
});

GSAPの rotation に +=${velocity * 0.05 と指定しています。 こうすることで、下スクロール時は角度がどんどん足されて右回転し、上スクロール時は角度が引かれて左回転するという動きを実装できます!

※ velocity の数値は激しくスクロールすると数千という大きな値になるため、そのまま使うと要素が高速回転しすぎます。そのため、0.05 のような係数を掛けて調整するのがコツです。

補足:公式ドキュメント

より詳しい仕様や最新の対応状況については、以下の公式ドキュメントをご参照ください。

・GSAP: getVelocity()

まとめ

今回は ScrollTrigger の velocity を使った少し特殊なUI実装をご紹介しました。

以前の progress が「ページのどの位置にいるか」という「絶対的な位置」を取得するのに対し、今回の velocity は「今どんな勢いで動いているか」という「瞬間的な値」を取得します。

これらを使い分けたり組み合わせたりすることで、ユーザーの操作にピタッと吸い付くような、気持ちの良いUIを作ることができます。ぜひ皆さんのWeb制作でも取り入れてみてください!

Prev
Next