1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【JavaScript】スクロールイベントスロットリングの実装方法

1
Posted at

実装例

以下は、スクロール位置を20ミリ秒ごとにスロットリングして処理する例です。

let lastKnownScrollPosition = 0;
let ticking = false;

function doSomething(scrollPos) {
  // スクロール位置を使った処理をここに記述
  console.log('スクロール位置:', scrollPos);
}

document.addEventListener("scroll", (event) => {
  lastKnownScrollPosition = window.scrollY;
  
  if (!ticking) {
    // 20ミリ秒ごとに処理を実行するようスロットリング
    setTimeout(() => {
      doSomething(lastKnownScrollPosition);
      ticking = false;
    }, 20);
    
    ticking = true;
  }
});
  1. tickingフラグ: 処理が実行中かどうかを管理
  2. lastKnownScrollPosition: 最新のスクロール位置を保持
  3. setTimeout: 指定した間隔(この例では20ms)で処理を実行

動作の流れ

  1. スクロールイベントが発火
  2. 最新のスクロール位置を記録
  3. tickingfalse の場合のみ、タイマーをセット
  4. タイマーが満了したら処理を実行し、tickingfalse に戻す
  5. その間に発火したスクロールイベントは無視され、最新の位置だけが保持される

IntersectionObserver

要素の可視性を監視するだけであれば、スクロールイベントではなくIntersectionObserver の使用を使用して以下のように実装できます。

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      // 要素が表示されたときの処理
    }
  });
});

observer.observe(document.querySelector('.target-element'));

requestAnimationFrameは使わない

requestAnimationFrame() を使ってスクロールイベントをスロットリングするのは、アニメーションフレームコールバックとスクロールイベントハンドラは同じ頻度で発火するため、効果がありません

代わりに setTimeout() を使って自分でタイムアウトを管理する必要があります。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?