【问题标题】:Choppy/Laggy scroll event on Chrome and IEChrome 和 IE 上的 Choppy/Laggy 滚动事件
【发布时间】:2012-06-13 13:37:09
【问题描述】:

我试图让内容块始终显示给用户,即使他向下滚动页面。他还应该能够上下滚动内容块。这是一个精简版本的小提琴,向您展示我的意思:

http://jsfiddle.net/9ehfV/2/

向下滚动时要注意,直到到达红色块的底部,它将将该块固定在窗口上,向上滚动时将其放回原处。

在 Firefox 中,可以上下滚动,上面描述的固定/取消固定是不可察觉的——像丝绸一样光滑。

但是,一旦尝试在 Chrome 或 IE 中滚动,滚动事件似乎会滞后,并且可以看到块“故障”一秒钟。这不是代码延迟——这似乎与浏览器有关。

有没有办法解决这个问题?我无计可施。

如果我能以不同的方式实现相同的效果,我会很感激建议...谢谢

【问题讨论】:

  • 我猜这与 Firefox 的滚动缓动方式以及 Gecko/Rhino 如何以不同于其他浏览器的方式触发/解释滚动事件有关,因此可能很难修复仍然使用scroll listener 方法,我没有看到任何其他可能的方法 atm,但祝你好运。

标签: javascript jquery google-chrome scroll scrolltop


【解决方案1】:

您是否尝试过一些用于滚动条的 jquery 插件或使用动画来向下和向上滚动?它将强制所有浏览器以相同的方式工作(或关闭足够多)..

Firefox(至少 v12)有一个“本机”滚动动画。当您浏览任何 URL 时,您会注意到滚动操作的流畅度,而这在其他浏览器(如 Chrome 或 IE)中没有实现。

jquery 滚动插件示例:

【讨论】:

  • 没有帮助。这些插件使用相同的滚动事件,实际上都没有为没有它的浏览器提供平滑滚动。也不能修复故障。
  • 这些插件只是一个例子。在一个简单的 google 搜索中还有很多其他的 jquery 滚动插件。您需要的是在没有默认滚动事件的情况下使用这些插件...您将需要“删除”滚动条并使用 scrollTo 动画和缓动插件进行自己的滚动...像这样stackoverflow.com/questions/4710438/… 您需要代码示例吗?
【解决方案2】:

由于 JavaScript 与 UI 在同一线程中运行,滚动事件回调可能会阻塞 UI 线程,从而导致延迟。您需要限制滚动事件侦听器,因为某些浏览器会触发很多事件侦听器。特别是如果您在 OS X 上使用模拟滚动设备。由于您在侦听器中进行了大量的高度计算,因此对于每个触发的滚动事件,it will trigger a reflow(非常昂贵)。

要限制侦听器,您必须防止侦听器每次都触发。通常你会等到浏览器在 x 毫秒内没有触发事件,或者在调用你的回调之间有最短时间。尝试调整值以查看效果。即使是 0 毫秒也有帮助,因为它会延迟回调的执行,直到浏览器有时间(通常是 5-40 毫秒)。

切换类以在状态(静态和固定位置)之间切换而不是在 JavaScript 中硬编码也是一个好习惯。然后,您可以更清晰地分离关注点和avoid potential extra redraws by mistake(请参阅“浏览器很聪明”部分)。 (example on 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 航点 由于您已经在使用 jQuery,我会看看 jQuery Waypoints 插件,它为您的问题提供了一个简单而优雅的解决方案。只需定义用户滚动到某个航点时的回调即可。

示例:(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
    });
});

【讨论】:

  • 哦,我明白了。滚动逻辑比我第一次复杂一点。认为有必要在固定位置之间进行一些计算,但类会简化固定位置。在这里更新了 jsfiddle:jsfiddle.net/b5hU8/4
  • +1 用于解释回流和重绘的链接,没有意识到这是我可以优化的东西。
  • 这根本不能回答 IE 滞后的问题。有时油门是你不需要的,例如,当你需要一个绝对定位的元素来跟随你的滚动时,它必须是即时的。但不在 IE 上。
  • 那么这个解决方案是否真的为任何人解决了 Chrome 中的问题?我尝试了几个版本但没有运气,尽管对此答案有一些积极的回应,虽然这是公认的答案,但我实际上并没有看到任何人确认它解决了问题。谢谢!
  • 这个答案可能会帮助人们解决不同的问题,但是 IE 中的 choppy/laggy scroll 动画不能通过限制滚动事件来解决。
猜你喜欢
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多