jQuery scroll()检测用户何时停止滚动

chr*_*ris 102 javascript jquery scroll jquery-events

好的,这个..

$(window).scroll(function()
{
    $('.slides_layover').removeClass('showing_layover');
    $('#slides_effect').show();
});
Run Code Online (Sandbox Code Playgroud)

我可以告诉别人什么时候滚动我的理解.因此,我试图找出当有人停下来时如何捕捉.从上面的示例中,您可以看到我正在滚动时从一组元素中删除一个类.但是,我想在用户停止滚动时重新启用该类.

这样做的原因是我打算在页面滚动时进行一个停留显示,以使页面具有我试图处理的特殊效果.但是我试图在滚动时删除的一个类与该效果冲突,因为它对某些性质具有透明效果.

yck*_*art 242

$(window).scroll(function() {
    clearTimeout($.data(this, 'scrollTimer'));
    $.data(this, 'scrollTimer', setTimeout(function() {
        // do something
        console.log("Haven't scrolled in 250ms!");
    }, 250));
});
Run Code Online (Sandbox Code Playgroud)

更新

我写了一个扩展来增强jQuery的默认on-event-handler.它将一个或多个事件的事件处理函数附加到所选元素,并在给定间隔未触发事件时调用处理函数.如果您只想在延迟之后触发回调(如resize事件等),这将非常有用.

检查github-repo以获取更新非常重要!

https://github.com/yckart/jquery.unevent.js

;(function ($) {
    var on = $.fn.on, timer;
    $.fn.on = function () {
        var args = Array.apply(null, arguments);
        var last = args[args.length - 1];

        if (isNaN(last) || (last === 1 && args.pop())) return on.apply(this, args);

        var delay = args.pop();
        var fn = args.pop();

        args.push(function () {
            var self = this, params = arguments;
            clearTimeout(timer);
            timer = setTimeout(function () {
                fn.apply(self, params);
            }, delay);
        });

        return on.apply(this, args);
    };
}(this.jQuery || this.Zepto));
Run Code Online (Sandbox Code Playgroud)

像任何其他onbind-event处理程序一样使用它,除了你可以传递一个额外的参数作为最后一个:

$(window).on('scroll', function(e) {
    console.log(e.type + '-event was 250ms not triggered');
}, 250);
Run Code Online (Sandbox Code Playgroud)

http://yckart.github.com/jquery.unevent.js/

(这个演示使用的是resize代替scroll,但谁在乎?!)


Sin*_*eta 46

使用jQuery油门/去抖动

对于像这样的问题,jQuery debounce是一个不错的选择.jsFidlle

$(window).scroll($.debounce( 250, true, function(){
    $('#scrollMsg').html('SCROLLING!');
}));
$(window).scroll($.debounce( 250, function(){
    $('#scrollMsg').html('DONE!');
}));
Run Code Online (Sandbox Code Playgroud)

第二个参数是"at_begin"标志.这里我展示了如何在"scroll start"和"scroll finish"中执行代码.

使用Lodash

正如Barry P所暗示的那样,jsFiddle,下划线或者lodash也有一个去抖动,每个都有不同的apis.

$(window).scroll(_.debounce(function(){
    $('#scrollMsg').html('SCROLLING!');
}, 150, { 'leading': true, 'trailing': false }));

$(window).scroll(_.debounce(function(){
    $('#scrollMsg').html('STOPPED!');
}, 150));
Run Code Online (Sandbox Code Playgroud)

  • 这是一个lo-dash版本:http://jsfiddle.net/barrypeterson/zzghqk62/ (3认同)

chr*_*ris 9

Rob W建议我在这里查看另一篇帖子,这篇文章基本上与我原来的帖子类似.通过我找到一个链接到网站:

http://james.padolsey.com/javascript/special-scroll-events-for-jquery/

这实际上最终有助于在我根据自己的需要进行一些调整之后非常好地解决我的问题,但总而言之帮助我获得了大量的guff并且让我节省了大约4个小时的时间来自行解决问题.

看到这篇文章似乎有一些优点,我想我会回来并提供最初在所提到的链接上找到的代码,以防作者曾决定与网站采取不同的方向并最终取消链接.

(function(){

    var special = jQuery.event.special,
        uid1 = 'D' + (+new Date()),
        uid2 = 'D' + (+new Date() + 1);

    special.scrollstart = {
        setup: function() {

            var timer,
                handler =  function(evt) {

                    var _self = this,
                        _args = arguments;

                    if (timer) {
                        clearTimeout(timer);
                    } else {
                        evt.type = 'scrollstart';
                        jQuery.event.handle.apply(_self, _args);
                    }

                    timer = setTimeout( function(){
                        timer = null;
                    }, special.scrollstop.latency);

                };

            jQuery(this).bind('scroll', handler).data(uid1, handler);

        },
        teardown: function(){
            jQuery(this).unbind( 'scroll', jQuery(this).data(uid1) );
        }
    };

    special.scrollstop = {
        latency: 300,
        setup: function() {

            var timer,
                    handler = function(evt) {

                    var _self = this,
                        _args = arguments;

                    if (timer) {
                        clearTimeout(timer);
                    }

                    timer = setTimeout( function(){

                        timer = null;
                        evt.type = 'scrollstop';
                        jQuery.event.handle.apply(_self, _args);

                    }, special.scrollstop.latency);

                };

            jQuery(this).bind('scroll', handler).data(uid2, handler);

        },
        teardown: function() {
            jQuery(this).unbind( 'scroll', jQuery(this).data(uid2) );
        }
    };

})();
Run Code Online (Sandbox Code Playgroud)


The*_*heo 5

我同意上面的一些评论,即监听超时不够准确,因为当您停止移动滚动条足够长的时间而不是停止滚动时会触发超时。我认为更好的解决方案是在用户开始滚动时立即听用户放开鼠标(mouseup):

$(window).scroll(function(){
    $('#scrollMsg').html('SCROLLING!');
    var stopListener = $(window).mouseup(function(){ // listen to mouse up
        $('#scrollMsg').html('STOPPED SCROLLING!');
        stopListner(); // Stop listening to mouse up after heard for the first time 
    });
});
Run Code Online (Sandbox Code Playgroud)

并且可以在此 JSFiddle 中看到它的工作示例

  • 这看起来很棒,但是如果您在触控板上通过 2 指手势或滚轮滚动,则不会触发 mouseup。这也可能是最常见的滚动方式,这使得它有问题。 (3认同)

Ily*_*ent 5

ES6 风格也带有检查滚动开始。

function onScrollHandler(params: {
  onStart: () => void,
  onStop: () => void,
  timeout: number
}) {
  const {onStart, onStop, timeout = 200} = params
  let timer = null

  return (event) => {
    if (timer) {
      clearTimeout(timer)
    } else {
      onStart && onStart(event)
    }
    timer = setTimeout(() => {
      timer = null
      onStop && onStop(event)
    }, timeout)
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

yourScrollableElement.addEventListener('scroll', onScrollHandler({
  onStart: (event) => {
    console.log('Scrolling has started')
  },
  onStop: (event) => {
    console.log('Scrolling has stopped')
  },
  timeout: 123 // Remove to use default value
}))
Run Code Online (Sandbox Code Playgroud)