2012-02-04 142 views
89

好这个..jQuery的滚动()检测时,用户会停止滚动

$(window).scroll(function() 
{ 
    $('.slides_layover').removeClass('showing_layover'); 
    $('#slides_effect').show(); 
}); 

,当有人从我的理解滚动我可以告诉。因此,我正试图弄清楚当某人停下来时该如何捕捉。从上面的例子中,你可以看到我正在滚动时正在从一组元素中移除一个类。但是,我想在用户停止滚动时重新启用该类。

原因是我的意图是在页面滚动时为了让页面产生一个我正在尝试的特殊效果而进行平移显示。但是,我正在试图去除的一个类,而滚动与这种效果的冲突,因为它对某种性质的透明度效应。

+1

可能重复[火灾事件scrollling后滚动条或鼠标滚轮的javascript](http://stackoverflow.com/questions/8931605/fire-event-after-scrollling -scrollbars-or-mousewheel-javascript) – 2012-02-04 21:11:52

+0

太棒了,不完全重复,但确切地说,我正在寻找和帮助我到最后解决我的问题的胡同。谢谢。 – chris 2012-02-04 22:05:02

回答

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

更新

我写了一个扩展以增强jQuery的默认on -event处理程序。它将一个或多个事件的事件处理函数附加到所选元素,并在事件未在给定时间间隔内触发时调用处理函数。如果您只想在延迟后触发回调,例如调整大小事件等,这很有用。

重要的是要检查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)); 

使用它像任何其他onbind -event处理程序,但您可以通过一个额外的参数作为最后:

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

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

(此演示使用resize而不是scroll,但谁在乎?)

+0

它仍然不是100%准确:有时用户停止并且即使在250毫秒后仍然继续滚动 – 2014-01-13 23:52:26

+0

此代码效果很好,但它完全破坏了jquery ui的自动完成小部件。 – kkazakov 2015-02-04 07:16:32

+0

@ArmanBimatov然后它会被视为用户不断滚动,这听起来不错,不是? – godblessstrawberry 2016-05-25 15:32:56

3

您可以设置运行每500毫秒左右的间隔,沿着下面的几行:

var curOffset, oldOffset; 
oldOffset = $(window).scrollTop(); 
var $el = $('.slides_layover'); // cache jquery ref 
setInterval(function() { 
    curOffset = $(window).scrollTop(); 
    if(curOffset != oldOffset) { 
    // they're scrolling, remove your class here if it exists 
    if($el.hasClass('showing_layover')) $el.removeClass('showing_layover'); 
    } else { 
    // they've stopped, add the class if it doesn't exist 
    if(!$el.hasClass('showing_layover')) $el.addClass('showing_layover'); 
    } 
    oldOffset = curOffset; 
}, 500); 

我还没有测试此代码,但原则应该工作。

44

使用jQuery油门/防抖动

jQuery debounce是一个很好的一个像这样的问题。 jsFidlle

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

第二个参数是“at_begin”标志。这里我已经展示了如何在“滚动开始”和“滚动完成”中执行代码。

使用Lodash

如所建议的由Barry P,jsFiddleunderscorelodash还具有防反跳,每个具有略微不同的API。

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

$(window).scroll(_.debounce(function(){ 
    $('#scrollMsg').html('STOPPED!'); 
}, 150)); 
+0

是否可以同时使用正常的滚动功能? $(window).scroll(function(){...}); – 2013-05-16 10:46:17

+0

当然,jQuery将绑定尽可能多的处理程序来处理事件。 – Sinetheta 2013-05-16 21:26:56

+3

这是一个lo-dash版本:http://jsfiddle.net/barrypeterson/zzghqk62/ – 2014-09-11 21:12:58

8

Rob W suggected我在这里查看另一个帖子,这个帖子基本上和我原来的帖子差不多。其中通过阅读我发现了一个链接到一个网站:

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

这实际上结束了帮助我自己的需要稍加调整后,非常漂亮,解决我的问题,但在所有的帮助得到了很多废话的并且为我省下了大约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)); 
     } 
    }; 

})(); 
2
function scrolled() { 
    //do by scroll start 
    $(this).off('scroll')[0].setTimeout(function(){ 
     //do by scroll end 
     $(this).on('scroll',scrolled); 
    }, 500) 
} 
$(window).on('scroll',scrolled); 

非常小的版本与

4

我有一些监听超时上述意见的约定开始和结束的能力是不够准确的,因为这将触发时你停止移动滚动条足够长的时间,而不是停止滚动。我想一个更好的解决办法是,尽快为他们开始滚动监听鼠标(鼠标松开)的用户不放:

$(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 
    }); 
}); 

和它的工作可以在this JSFiddle

+2

这看起来不错,但是如果您是通过触控板或滚轮上的2指手势滚动,则不会触发mouseup。这可能是最常见的滚动方式,这会造成问题。 – Adam 2014-03-20 21:15:39

+1

好点。但可能有一些解决方案。使用jquery的'mousewheel'事件或跟踪如果mousedown第一,并使用其他人建议的超时方法。但我认为使用鼠标滚轮事件的其他答案的组合和滚动条拖动这个答案将给出最准确的结果 – Theo 2014-03-21 09:29:07

1

可以看到的一个例子确定这是我之前用过的东西。 基本上你看起来是最后一个参考scrollTop()。 清除超时后,您检查当前的scrollTop(),如果它们相同,则完成滚动。

$(window).scroll((e) -> 
    clearTimeout(scrollTimer) 
    $('header').addClass('hidden') 

    scrollTimer = setTimeout((() -> 
    if $(this).scrollTop() is currentScrollTop 
     $('header').removeClass('hidden') 
), animationDuration) 

    currentScrollTop = $(this).scrollTop() 
) 
0

请的jquery mobile scrollstop event

$(document).on("scrollstop",function(){ 
    alert("Stopped scrolling!"); 
}); 
+3

这是jQuery的移动,而不是jQuery的。我差点陷入同一陷阱;) – katzenhut 2015-08-12 14:52:33