检测滚动事件是否由用户创build

是否可以告诉滚动事件是由浏览器还是由用户完成? 具体来说,当使用后退button时,浏览器可以跳转到最后已知的滚动位置。 如果我绑定滚动事件我怎么知道这是由用户还是浏览器引起的?

$(document).scroll( function(){ //who did this?! }); 

我看到三种导致在浏览器中滚动的情况。

  1. 用户执行一些操作。 例如,使用鼠标滚轮,箭头键,页面上/下键,家庭/结束键。
  2. 浏览器会自动滚动。 例如,在浏览器中使用后退button时,它将自动跳转到最后一个已知的滚动位置。
  3. JavaScript卷轴。 例如, element.scrollTo(x,y)

不幸的是,没有直接的说法。

我会说,如果你可以重新devise你的应用程序,以便它不依赖于这种types的stream程,去那个。

如果没有,我能想到的解决方法是跟踪用户启动的卷轴,并检查是否浏览器或用户触发滚动。

这里有一个例子,我把它放在一起做得很好(jQuery历史logging遇到问题的浏览器除外)。

你需要在本地运行,以便能够完全testing(jsFiddle / jsbin不适合,因为它们是iFrame的内容)。

以下是我validation的testing用例

  • 页面加载 – userScrollfalse
  • 使用鼠标/键盘滚动 – userScroll变为true
  • 点击链接跳转到页面底部 – userScroll变为false
  • 点击返回/转发 – userScroll变为false ;

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <script src="http://code.jquery.com/jquery-1.6.1.min.js"></script> <script type="text/javascript" src="https://raw.github.com/tkyk/jquery-history-plugin/master/jquery.history.js"></script> </head> <body> <span> hello there </span><br/> <a href="#bottom"> click here to go down </a> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <a name="bottom"> just sitting </a> </body> <script type="text/javascript"> var userScroll = false; function mouseEvent(e) { userScroll = true; } $(function() { // reset flag on back/forward $.history.init(function(hash){ userScroll = false; }); $(document).keydown(function(e) { if(e.which == 33 // page up || e.which == 34 // page dn || e.which == 32 // spacebar || e.which == 38 // up || e.which == 40 // down || (e.ctrlKey && e.which == 36) // ctrl + home || (e.ctrlKey && e.which == 35) // ctrl + end ) { userScroll = true; } }); // detect user scroll through mouse // Mozilla/Webkit if(window.addEventListener) { document.addEventListener('DOMMouseScroll', mouseEvent, false); } //for IE/OPERA etc document.onmousewheel = mouseEvent; // to reset flag when named anchors are clicked $('a[href*=#]').click(function() { userScroll = false; }); // detect browser/user scroll $(document).scroll( function(){ console.log('Scroll initiated by ' + (userScroll == true ? "user" : "browser")); }); }); </script> </html> 

笔记:

  • 当用户用鼠标拖动滚动条时,这不会跟踪滚动。 这可以添加更多的代码,我作为一个练习留给你。
  • event.keyCodes可能因操作系统而异,所以您可能需要适当地更改。

希望这可以帮助!

据我所知,每当“用户”或其他方式发出滚动事件时,都不可能(没有任何工作)。

你可以尝试(像其他人提到的)抓住mousewheel事件,然后可能试图捕捉任何键可以触发滚动(箭头,空格等),当检查当前聚焦的元素,因为你例如不能滚动使用箭头键在input字段中input。 一般来说,这将是复杂和凌乱的脚本。

根据你处理的情况,我可以猜测“还原逻辑”,而不是检测用户发出的滚动事件,只是挂钩进入任何滚动编程,并处理任何滚动事件不是由您的代码所做的用户。 就像我说的,这取决于一种情况,以及你想要达到的目标。

尝试使用Mousewheel和DOMMouseScroll事件。 见http://www.quirksmode.org/dom/events/scroll.html

是的,这是100%的可能性。 我目前正在使用IE浏览器不是一个要求的应用程序 – 只有客户端。 当我的Backbone应用程序启动一个animation滚动改变 – 滚动发生,但不会触发这些事件捕获。 这是在FF,Safari和Chrome最新testing。

 $('html, body').bind('scroll mousedown wheel DOMMouseScroll mousewheel keyup', function(evt) { // detect only user initiated, not by an .animate though if (evt.type === 'DOMMouseScroll' || evt.type === 'keyup' || evt.type === 'mousewheel') { // up if (evt.originalEvent.detail < 0 || (evt.originalEvent.wheelDelta && evt.originalEvent.wheelDelta > 0)) { // down. } else if (evt.originalEvent.detail > 0 || (evt.originalEvent.wheelDelta && evt.originalEvent.wheelDelta < 0)) { } } }); 

您可以检查准备就绪的滚动位置。 当您启动滚动事件检查时,确保滚动位置与加载页面时不同。 一旦页面滚动,最后一定要清除存储的值。

 $(function () { var loadScrollTop = ($(document).scrollTop() > 0 ? $(document).scrollTop() : null); $(document).scroll(function (e) { if ( $(document).scrollTop() !== loadScrollTop) { // scroll code here! } loadScrollTop = null; }); }); 

发现这非常有用。 这是一个倾向于咖啡的脚本版本。

 $ -> S.userScroll = false # reset flag on back/forward if $.history? $.history.init (hash) -> S.userScroll = false mouseEvent = (e)-> S.userScroll = true $(document).keydown (e) -> importantKey = (e.which == 33 or # page up e.which == 34 or # page dn e.which == 32 or # spacebar e.which == 38 or # up e.which == 40 or # down (e.ctrlKey and e.which == 36) or # ctrl + home (e.ctrlKey and e.which == 35) # ctrl + end ) if importantKey S.userScroll = true; # Detect user scroll through mouse # Mozilla/Webkit if window.addEventListener document.addEventListener('DOMMouseScroll', mouseEvent, false); # for IE/OPERA etc document.onmousewheel = mouseEvent; 

如果您使用的是JQuery而不是更好的答案,显然 – 我只是自己尝试一下。

请参阅: 检测用户的jQuery事件触发器或通过代码调用

关于:

具体来说,当使用后退button时,浏览器可以跳转到最后已知的滚动位置。

在页面呈现后,很快就会触发。 你可以延迟1秒左右的滚动事件的监听。