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);
参考
以上、ありがとうございました。