jQuery 如何检测滚动方向

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7154967/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 23:28:44  来源:igfitidea点击:

How to detect scroll direction

jqueryscrolldirection

提问by Rik de Vos

I want to run a function when someone scrolls down on an element. Something like this:

当有人向下滚动元素时,我想运行一个函数。像这样的东西:

 $('div').scrollDown(function(){ alert('down') });
 $('div').scrollUp(function(){ alert('up') });

But those functions don't exist. Is there a solution to this problem? Awwwardsseem to be able to do it (logo in navbar changes depending on scroll direction). Unfortunately, the source code is compressed, so no luck there...

Thanks!!

但这些功能并不存在。这个问题有解决方案吗?Awwwards似乎能够做到(导航栏中的徽标会根据滚动方向而变化)。不幸的是,源代码被压缩,所以没有运气...

谢谢!

回答by Rik de Vos

I managed to figure it out in the end, so if anyone is looking for the answer:

最后我设法弄明白了,所以如果有人在寻找答案:

 //Firefox
 $('#elem').bind('DOMMouseScroll', function(e){
     if(e.originalEvent.detail > 0) {
         //scroll down
         console.log('Down');
     }else {
         //scroll up
         console.log('Up');
     }

     //prevent page fom scrolling
     return false;
 });

 //IE, Opera, Safari
 $('#elem').bind('mousewheel', function(e){
     if(e.originalEvent.wheelDelta < 0) {
         //scroll down
         console.log('Down');
     }else {
         //scroll up
         console.log('Up');
     }

     //prevent page fom scrolling
     return false;
 });

回答by honk31

Following example will listen to MOUSE scroll only, no touch nor trackpad scrolls.

以下示例将仅收听 MOUSE 滚动,不收听触摸或触控板滚动。

It uses jQuery.on()(As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document).

它使用jQuery.on()(从 jQuery 1.7 开始,.on() 方法是将事件处理程序附加到文档的首选方法)。

$('#elem').on( 'DOMMouseScroll mousewheel', function ( event ) {
  if( event.originalEvent.detail > 0 || event.originalEvent.wheelDelta < 0 ) { //alternative options for wheelData: wheelDeltaX & wheelDeltaY
    //scroll down
    console.log('Down');
  } else {
    //scroll up
    console.log('Up');
  }
  //prevent page fom scrolling
  return false;
});

Works on all browsers.

适用于所有浏览器。

fiddle: http://jsfiddle.net/honk1/gWnNv/7/

小提琴:http: //jsfiddle.net/honk1/gWnNv/7/

回答by Shikkediel

This one deserves an update - nowadays we have the wheelevent :

这个值得更新 - 现在我们有这样的wheel活动:

$(function() {

$(window).on('wheel', function(e) {

 var delta = e.originalEvent.deltaY;

 if (delta > 0) $('body').text('down');
 else $('body').text('up');

 return false; // this line is only added so the whole page won't scroll in the demo
});
});
body {
  font-size: 22px;
  text-align: center;
  color: white;
  background: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Support has been pretty good on modern browsers for quite a while already :

对现代浏览器的支持已经很长时间了:

  • Chrome 31+
  • Firefox 17+
  • IE9+
  • Opera 18+
  • Safari 7+
  • 铬 31+
  • 火狐 17+
  • IE9+
  • 歌剧 18+
  • Safari 7+

https://developer.mozilla.org/en-US/docs/Web/Events/wheel

https://developer.mozilla.org/en-US/docs/Web/Events/wheel

If deeper browser support is required, probably best to use mousewheel.js instead of messing about :

如果需要更深入的浏览器支持,最好使用 mousewheel.js 而不是搞乱:

https://plugins.jquery.com/mousewheel/

https://plugins.jquery.com/mousewheel/

$(function() {

$(window).mousewheel(function(turn, delta) {

 if (delta > 0) $('body').text('up');
 else $('body').text('down');

 return false; // this line is only added so the whole page won't scroll in the demo
});
});
body {
  font-size: 22px;
  text-align: center;
  color: white;
  background: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"></script>

回答by Chemical Programmer

Existing Solution

现有解决方案

There could be 3 solutionfrom this posting and other stackoverflow article.

这篇文章和其他 stackoverflow 文章可能有3 个解决方案

Solution 1

解决方案1

    var lastScrollTop = 0;
    $(window).on('scroll', function() {
        st = $(this).scrollTop();
        if(st < lastScrollTop) {
            console.log('up 1');
        }
        else {
            console.log('down 1');
        }
        lastScrollTop = st;
    });

Solution 2

解决方案2

    $('body').on('DOMMouseScroll', function(e){
        if(e.originalEvent.detail < 0) {
            console.log('up 2');
        }
        else {
            console.log('down 2');
        }
    });

Solution 3

解决方案3

    $('body').on('mousewheel', function(e){
        if(e.originalEvent.wheelDelta > 0) {
            console.log('up 3');
        }
        else {
            console.log('down 3');
        }
    });


Multi Browser Test

多浏览器测试

I couldn't tested it on Safari

我无法在 Safari 上对其进行测试

chrome 42 (Win 7)

铬 42(赢 7)

  • Solution 1
    • Up : 1 event per 1 scroll
    • Down : 1 event per 1 scroll
  • Soltion 2
    • Up : Not working
    • Down : Not working
  • Solution 3
    • Up : 1 event per 1 scroll
    • Down : 1 event per 1 scroll
  • 解决方案1
    • 向上:每 1 个滚动 1 个事件
    • 向下:每 1 个滚动 1 个事件
  • 解决方案 2
    • 上:不工作
    • 向下:不工作
  • 解决方案3
    • 向上:每 1 个滚动 1 个事件
    • 向下:每 1 个滚动 1 个事件

Firefox 37 (Win 7)

火狐 37 (Win 7)

  • Solution 1
    • Up : 20 events per 1 scroll
    • Down : 20 events per 1 scroll
  • Soltion 2
    • Up : Not working
    • Down : 1 event per 1 scroll
  • Solution 3
    • Up : Not working
    • Down : Not working
  • 解决方案1
    • 向上:每 1 个滚动 20 个事件
    • 向下:每 1 个滚动 20 个事件
  • 解决方案 2
    • 上:不工作
    • 向下:每 1 个滚动 1 个事件
  • 解决方案3
    • 上:不工作
    • 向下:不工作

IE 11 (Win 8)

IE 11(赢8)

  • Solution 1
    • Up : 10 events per 1 scroll (side effect : down scroll occured at last)
    • Down : 10 events per 1 scroll
  • Soltion 2
    • Up : Not working
    • Down : Not working
  • Solution 3
    • Up : Not working
    • Down : 1 event per 1 scroll
  • 解决方案1
    • 向上:每 1 个滚动 10 个事件(副作用:最后发生向下滚动)
    • 向下:每 1 个滚动 10 个事件
  • 解决方案 2
    • 上:不工作
    • 向下:不工作
  • 解决方案3
    • 上:不工作
    • 向下:每 1 个滚动 1 个事件

IE 10 (Win 7)

IE 10(赢 7)

  • Solution 1
    • Up : 1 event per 1 scroll
    • Down : 1 event per 1 scroll
  • Soltion 2
    • Up : Not working
    • Down : Not working
  • Solution 3
    • Up : 1 event per 1 scroll
    • Down : 1 event per 1 scroll
  • 解决方案1
    • 向上:每 1 个滚动 1 个事件
    • 向下:每 1 个滚动 1 个事件
  • 解决方案 2
    • 上:不工作
    • 向下:不工作
  • 解决方案3
    • 向上:每 1 个滚动 1 个事件
    • 向下:每 1 个滚动 1 个事件

IE 9 (Win 7)

IE 9(赢 7)

  • Solution 1
    • Up : 1 event per 1 scroll
    • Down : 1 event per 1 scroll
  • Soltion 2
    • Up : Not working
    • Down : Not working
  • Solution 3
    • Up : 1 event per 1 scroll
    • Down : 1 event per 1 scroll
  • 解决方案1
    • 向上:每 1 个滚动 1 个事件
    • 向下:每 1 个滚动 1 个事件
  • 解决方案 2
    • 上:不工作
    • 向下:不工作
  • 解决方案3
    • 向上:每 1 个滚动 1 个事件
    • 向下:每 1 个滚动 1 个事件

IE 8 (Win 7)

IE 8(赢 7)

  • Solution 1
    • Up : 2 events per 1 scroll (side effect : down scroll occured at last)
    • Down : 2~4 events per 1 scroll
  • Soltion 2
    • Up : Not working
    • Down : Not working
  • Solution 3
    • Up : 1 event per 1 scroll
    • Down : 1 event per 1 scroll
  • 解决方案1
    • 向上:每 1 次滚动 2 个事件(副作用:最后发生向下滚动)
    • 向下:每 1 个滚动 2~4 个事件
  • 解决方案 2
    • 上:不工作
    • 向下:不工作
  • 解决方案3
    • 向上:每 1 个滚动 1 个事件
    • 向下:每 1 个滚动 1 个事件


Combined Solution

组合解决方案

I checked that side effect from IE 11 and IE 8 is come from if elsestatement. So, I replaced it with if else ifstatement as following.

我检查了 IE 11 和 IE 8 的副作用来自if else声明。所以,我用if else if下面的语句替换了它。

From the multi browser test, I decided to use Solution 3for common browsers and Solution 1for firefox and IE 11.

从多浏览器测试来看,我决定对常用浏览器使用解决方案3,对firefox和IE 11使用解决方案1

I referred this answerto detect IE 11.

我参考了这个答案来检测 IE 11。

    // Detect IE version
    var iev=0;
    var ieold = (/MSIE (\d+\.\d+);/.test(navigator.userAgent));
    var trident = !!navigator.userAgent.match(/Trident\/7.0/);
    var rv=navigator.userAgent.indexOf("rv:11.0");

    if (ieold) iev=new Number(RegExp.);
    if (navigator.appVersion.indexOf("MSIE 10") != -1) iev=10;
    if (trident&&rv!=-1) iev=11;

    // Firefox or IE 11
    if(typeof InstallTrigger !== 'undefined' || iev == 11) {
        var lastScrollTop = 0;
        $(window).on('scroll', function() {
            st = $(this).scrollTop();
            if(st < lastScrollTop) {
                console.log('Up');
            }
            else if(st > lastScrollTop) {
                console.log('Down');
            }
            lastScrollTop = st;
        });
    }
    // Other browsers
    else {
        $('body').on('mousewheel', function(e){
            if(e.originalEvent.wheelDelta > 0) {
                console.log('Up');
            }
            else if(e.originalEvent.wheelDelta < 0) {
                console.log('Down');
            }
        });
    }

回答by AlienWebguy

$(function(){
    var _top = $(window).scrollTop();
    var _direction;
    $(window).scroll(function(){
        var _cur_top = $(window).scrollTop();
        if(_top < _cur_top)
        {
            _direction = 'down';
        }
        else
        {
            _direction = 'up';
        }
        _top = _cur_top;
        console.log(_direction);
    });
});

Demo: http://jsfiddle.net/AlienWebguy/Bka6F/

演示:http: //jsfiddle.net/AlienWebguy/Bka6F/

回答by Erick Petrucelli

Here is a sampleshowing an easy way to do it. The script is:

这是一个示例,展示了一种简单的方法。脚本是:

$(function() {
  var _t = $("#container").scrollTop();
  $("#container").scroll(function() {
    var _n = $("#container").scrollTop();
    if (_n > _t) {
      $("#target").text("Down");
    } else {
      $("#target").text("Up");
    }
    _t = _n;
  });
});

The #containeris your div id. The #targetis just to see it working. Change to what you want when up or when down.

#container是你的 div id。该#target是刚才看到它的工作。上升或下降时更改为您想要的。

EDIT

编辑

The OP didn't say before, but since he's using a div with overflow: hidden, scrolling doesn't occur, then the script to detect the scroll is the least of it. Well, how to detect something that does not happen?!

OP 之前没有说,但由于他使用 div 和overflow: hidden,滚动不会发生,那么检测滚动的脚本是最少的。那么,如何检测不会发生的事情?!

So, the OP himself posted the link with what he wants, so why not use that library? http://cdn.jquerytools.org/1.2.5/full/jquery.tools.min.js.

所以,OP 自己发布了他想要的链接,那么为什么不使用那个库呢?http://cdn.jquerytools.org/1.2.5/full/jquery.tools.min.js

The call is just:

电话只是:

$(function() {
    $(".scrollable").scrollable({ vertical: true, mousewheel: true });
});

回答by Jithin U. Ahmed

var mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel" //FF doesn't recognize mousewheel as of FF3.x
$(document).bind(mousewheelevt, 
function(e)
    {
        var evt = window.event || e //equalize event object     
        evt = evt.originalEvent ? evt.originalEvent : evt; //convert to originalEvent if possible               
        var delta = evt.detail ? evt.detail*(-40) : evt.wheelDelta //check for detail first, because it is used by Opera and FF
        if(delta > 0) 
            {
            scrollup();
            }
        else
            {
            scrolldown();
            }   
    }
);

回答by user122293

You can use this simple plugin to add scrollUpand scrollDownto your jQuery

您可以使用这个简单的插件来添加scrollUp和添加scrollDown到您的 jQuery

https://github.com/phpust/JQueryScrollDetector

https://github.com/phpust/JQueryScrollDetector

var lastScrollTop = 0;
var action = "stopped";
var timeout = 100;
// Scroll end detector:
$.fn.scrollEnd = function(callback, timeout) {    
      $(this).scroll(function(){
        // get current scroll top 
        var st = $(this).scrollTop();
        var $this = $(this);
        // fix for page loads
        if (lastScrollTop !=0 )
        {
            // if it's scroll up
            if (st < lastScrollTop){
                action = "scrollUp";
            } 
            // else if it's scroll down
            else if (st > lastScrollTop){
                action = "scrollDown";
            }
        }
        // set the current scroll as last scroll top
        lastScrollTop = st;
        // check if scrollTimeout is set then clear it
        if ($this.data('scrollTimeout')) {
          clearTimeout($this.data('scrollTimeout'));
        }
        // wait until timeout done to overwrite scrolls output
        $this.data('scrollTimeout', setTimeout(callback,timeout));
    });
};

$(window).scrollEnd(function(){
    if(action!="stopped"){
        //call the event listener attached to obj.
        $(document).trigger(action); 
    }
}, timeout);