LoginSignup
20
15

More than 5 years have passed since last update.

jsイベント間引き(throttle+debounce)

Last updated at Posted at 2019-04-07

scrollやresizeなど、大量のイベントが発生する処理はフレームレート低下によるアニメーションのカクつきや、CPUに不要な負荷をかけてしまうことがあるため、適宜処理を間引きをすると良いです。

throttle … 実行してから一定時間内に発生した処理を無視
debounce … 連続したイベントの最後だけ実行

throttle は一定時間の処理が無視されるため、スクロール端に到達時のタイミングによっては必要な処理が実行されないことがあるので、debounceと組み合わせてみました。

また、まれに throttle と debounce の時間差が1フレーム以下の場合に同時に発火してしまうことがあったので、重複実行しないよう debounceDelay で調整しています。
※1フレーム(1/60fps)= 1/60秒 = 約16ms

サンプルではインターバル時間 256ms(16フレーム)をデフォルト値にしていますが、もっと細かい精度が必要な場合は、設定時間を短くしてください。※16ms(1フレーム)以下に設定すると間引きしないのとほぼ同義(無意味)となります

sample

native

var throttle = (function(callback, interval = 256) {
  var time = Date.now(),
      lag,
      debounceTimer,
      debounceDelay = 16;

  return function(callback) {
    lag = time + interval - Date.now();
    if (lag < 0) {
      //console.log( time + ":throttle:" + lag);
      callback();
      time = Date.now();
    } else {
      clearTimeout(debounceTimer);
      debounceTimer = setTimeout(function() {
        //console.log( time + ":debounce:" + (interval - lag + debounceDelay));
        callback();
      }, (interval - lag + debounceDelay));
    }
  }
})();

// 間引きしたい処理
var myCallback = function() {
  console.log("myCallback");
};

// イベント発火
window.addEventListener('scroll', function() {
  throttle(myCallback);
  //throttle(myCallback,64); //第二引数 インターバル時間
});

jquery


(function($) {

  $.fn.throttle = function(callback, options) {
    options = $.extend({
      interval: 256
    }, options);
    var time = Date.now(),
        lag,
        debounceTimer,
        debounceDelay = 16;

    return function() {
      lag = time + options.interval - Date.now();
      if (lag < 0) {
        //console.log( time + ":throttle:" + lag);
        callback();
        time = Date.now();
      } else {
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(function() {
          //console.log( time + ":debounce:" + (options.interval - lag + debounceDelay));
          callback();
        }, (options.interval - lag + debounceDelay));
      }
    }
  };

  var myCallback = function() {
    console.log("myCallback");
  };

  $(window).on('scroll', $.fn.throttle(myCallback));

  //$(window).on('scroll', $.fn.throttle(myCallback,{
  //  interval: 64  //オプション
  //}));

})(jQuery);

参考

以上、ありがとうございました。

20
15
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
20
15