JavaScriptはUIと同じスレッドで実行されるため、スクロールイベントコールバックはUIスレッドをブロックし、ラグを引き起こす可能性があります。一部のブラウザは多くのイベントリスナーを起動するため、スクロールイベントリスナーを調整する必要があります。特に、アナログスクロールデバイスを搭載したOSXを使用している場合。リスナーで多くの高さ計算を行うため、発生するすべてのスクロールイベントに対してリフロー(非常に高価)がトリガーされます。
リスナーを絞るには、リスナーが毎回発火しないようにする必要があります。通常、ブラウザがxミリ秒の間イベントをトリガーしなくなるまで待つか、コールバックを呼び出すまでの間に最小の時間があります。値を調整して効果を確認してください。ブラウザに時間がかかるまで(通常は5〜40ミリ秒)コールバックの実行が遅れるため、0ミリ秒でも役立ちます。
また、JavaScriptでハードコーディングするのではなく、クラスを切り替えて状態(静的位置と固定位置)を切り替えることもお勧めします。そうすれば、関心の分離がより明確になり、誤って余分に再描画される可能性を回避できます(「ブラウザは賢い」セクションを参照)。(jsfiddleの例)
xミリ秒の一時停止を待ちます
// return a throttled function
function waitForPause(ms, callback) {
var timer;
return function() {
var self = this, args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
callback.apply(self, args);
}, ms);
};
}
this.start = function() {
// wrap around your callback
$window.scroll( waitForPause( 30, self.worker ) );
};
少なくともxミリ秒待つ(jsfiddle)
function throttle(ms, callback) {
var timer, lastCall=0;
return function() {
var now = new Date().getTime(),
diff = now - lastCall;
console.log(diff, now, lastCall);
if (diff >= ms) {
console.log("Call callback!");
lastCall = now;
callback.apply(this, arguments);
}
};
}
this.start = function() {
// wrap around your callback
$window.scroll(throttle(30, self.worker));
};
jQuery Waypoints
すでにjQueryを使用しているので、問題に対するシンプルでエレガントなソリューションを備えたjQueryWaypointsプラグインを見てみましょう。ユーザーが特定のウェイポイントまでスクロールしたときのコールバックを定義するだけです。
例:(jsfiddle)
$(document).ready(function() {
// throttling is built in, just define ms
$.waypoints.settings.scrollThrottle = 30;
$('#content').waypoint(function(event, direction) {
$(this).toggleClass('sticky', direction === "down");
event.stopPropagation();
}, {
offset: 'bottom-in-view' // checkpoint at bottom of #content
});
});