Javascript Chrome 和 IE 上的断断续续/滞后滚动事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10966710/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Choppy/Laggy scroll event on Chrome and IE
提问by Marcelo Mason
I am trying to have a content block always be shown to the user, even if he scrolls way down the page. He should also be able to scroll up and down the content block. Here is a fiddle with a stripped down version to show you what I mean:
我试图让内容块始终显示给用户,即使他向下滚动页面也是如此。他还应该能够上下滚动内容块。这是一个带有精简版本的小提琴,向您展示我的意思:
One should notice when scrolling down, until reaching the bottom of the red block, it will fix the block on the window, and when scrolling back up, it places it back.
向下滚动时要注意,直到到达红色块的底部,它才会将块固定在窗口上,当向上滚动时,它会放回原处。
In Firefox one can scroll up and down and the fixing/unfixing described above is imperceptible – smooth as silk.
在 Firefox 中可以上下滚动,上面描述的固定/取消固定是难以察觉的——像丝绸一样光滑。
Once one tries scrolling in Chrome or IE, though, it seems like the scroll event lags and one can see the block "glitching" for a second. It's not code lag – it seems to be something with the browsers.
但是,一旦尝试在 Chrome 或 IE 中滚动,滚动事件似乎滞后并且可以看到块“故障”一秒钟。这不是代码延迟——这似乎是浏览器的问题。
Is there any way to fix this? I'm at my wit's end.
有没有什么办法解决这一问题?我已经无计可施了。
I'd appreciate suggestions on how I can achieve the same effect in a different way...thanks
我很感激有关如何以不同方式实现相同效果的建议......谢谢
回答by gregers
Since JavaScript runs in the same thread as the UI, a scroll event callback can block the UI-thread and thus cause lag. You need to throttle the scroll event listener because some browsers fire a lot of them. Especially if you're on OS X with an analog scroll device. Since you do a lot of height calculations in your listener, it will trigger a reflow(very expensive) for every scroll event that is fired.
由于 JavaScript 在与 UI 相同的线程中运行,滚动事件回调可能会阻塞 UI 线程,从而导致延迟。您需要限制滚动事件侦听器,因为某些浏览器会触发大量事件。特别是如果您使用的是带有模拟滚动设备的 OS X。由于您在侦听器中进行了大量高度计算,因此它会为每个触发的滚动事件触发回流(非常昂贵)。
To throttle the listener, you have to prevent the listener from firing every time. Usually you wait until the browser doesn't trigger an event for x milliseconds, or have a minimum time between calling your callback. Try adjusting the value to see the effect. Even 0 milliseconds can help, since it will delay the execution of the callback until the browser has time (usually 5-40 ms).
要限制监听器,您必须防止监听器每次都触发。通常你会等到浏览器在 x 毫秒内没有触发事件,或者在调用回调之间有最短时间。尝试调整值以查看效果。即使是 0 毫秒也有帮助,因为它会延迟回调的执行,直到浏览器有时间(通常是 5-40 毫秒)。
It's also a good practice to toggle a class to switch between states (static and fixed position) instead of hard-coding it in JavaScript. Then you have a cleaner separation of concerns and avoid potential extra redraws by mistake(see "Browsers are smart" section). (example on jsfiddle)
切换类以在状态(静态和固定位置)之间切换,而不是在 JavaScript 中对其进行硬编码也是一种很好的做法。然后,您可以更清晰地分离关注点并避免错误地潜在的额外重绘(请参阅“浏览器是智能的”部分)。(jsfiddle 上的例子)
Wait for a pause of x ms
等待 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 ) );
};
Wait at least x ms(jsfiddle)
至少等待 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 WaypointsSince you're already using jQuery, I would have a look at the jQuery Waypointsplugin which has a simple and elegant solution to your problem. Just define a callback when the user scrolls to a certain waypoint.
jQuery Waypoints由于您已经在使用 jQuery,我会看看jQuery Waypoints插件,它为您的问题提供了一个简单而优雅的解决方案。当用户滚动到某个航点时,只需定义一个回调。
Example: (jsfiddle)
示例:(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
});
});
回答by Rafael Verger
Have you tried some jquery plugin for scrollbar or uses animation to scroll down and up? It will force all browsers to work at the same way (or closes enought)..
您是否尝试过一些 jquery 滚动条插件或使用动画向下和向上滚动?它将强制所有浏览器以相同的方式工作(或关闭足够多)。
What happens is that firefox (at least v12) have a "native" scroll animation. When you navigate for any URL you can notice the smoothness for scroll actions and this is not implemented in other browsers, like Chrome or IE.
发生的事情是 firefox(至少 v12)有一个“原生”滚动动画。当您浏览任何 URL 时,您会注意到滚动操作的平滑度,而这在其他浏览器(如 Chrome 或 IE)中没有实现。
Examples for jquery scroller plugins:
jquery 滚动插件示例: