Javascript 如何确定 jQuery 滚动事件的方向?

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

How can I determine the direction of a jQuery scroll event?

javascriptjquery

提问by Zach

I'm looking for something to this effect:

我正在寻找这种效果的东西:

$(window).scroll(function(event){
   if (/* magic code*/ ){
       // upscroll code
   } else {
      // downscroll code
   }
});

Any ideas?

有任何想法吗?

回答by Josiah Ruddell

Check current scrollTopvs previous scrollTop

检查当前scrollTop与以前scrollTop

var lastScrollTop = 0;
$(window).scroll(function(event){
   var st = $(this).scrollTop();
   if (st > lastScrollTop){
       // downscroll code
   } else {
      // upscroll code
   }
   lastScrollTop = st;
});

回答by cilphex

You can do it without having to keep track of the previous scroll top, as all the other examples require:

您无需跟踪前一个滚动顶部即可完成此操作,因为所有其他示例都需要:

$(window).bind('mousewheel', function(event) {
    if (event.originalEvent.wheelDelta >= 0) {
        console.log('Scroll up');
    }
    else {
        console.log('Scroll down');
    }
});

I am not an expert on this so feel free to research it further, but it appears that when you use $(element).scroll, the event being listened for is a 'scroll' event.

我不是这方面的专家,因此请随意进一步研究,但似乎当您使用 时$(element).scroll,正在侦听的事件是“滚动”事件。

But if you specifically listen for a mousewheelevent by using bind, the originalEventattribute of the event parameter to your callback contains different information. Part of that information is wheelDelta. If it's positive, you moved the mousewheel up. If it's negative, you moved the mousewheel down.

但是,如果您专门mousewheel使用 bind侦听事件,则originalEvent回调的事件参数的属性包含不同的信息。该信息的一部分是wheelDelta. 如果是肯定的,则您将鼠标滚轮向上移动。如果它是负数,则将鼠标滚轮向下移动。

My guess is that mousewheelevents will fire when the mouse wheel turns, even if the page does not scroll; a case in which 'scroll' events probably are not fired. If you want, you can call event.preventDefault()at the bottom of your callback to prevent the page from scrolling, and so that you can use the mousewheel event for something other than a page scroll, like some type of zoom functionality.

我的猜测是mousewheel,即使页面不滚动,鼠标滚轮转动时也会触发事件;可能不会触发“滚动”事件的情况。如果需要,您可以event.preventDefault()在回调的底部调用以防止页面滚动,这样您就可以将 mousewheel 事件用于页面滚动以外的其他内容,例如某种类型的缩放功能。

回答by Skilldrick

Store the previous scroll location, then see if the new one is greater than or less than that.

存储之前的滚动位置,然后查看新的滚动位置是大于还是小于该位置。

Here's a way to avoid any global variables (fiddle available here):

这是一种避免任何全局变量的方法(此处提供小提琴):

(function () {
    var previousScroll = 0;

    $(window).scroll(function(){
       var currentScroll = $(this).scrollTop();
       if (currentScroll > previousScroll){
           alert('down');
       } else {
          alert('up');
       }
       previousScroll = currentScroll;
    });
}()); //run this anonymous function immediately

回答by Chemical Programmer

Existing Solution

现有解决方案

There could be 3 solutionfrom this posting and other answer.

这个帖子和其他答案可能有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 souporserious

I understand there has already been an accepted answer, but wanted to post what I am using in case it can help anyone. I get the direction like cliphexwith the mousewheel event but with support for Firefox. It's useful doing it this way in case you are doing something like locking scroll and can't get the current scroll top.

我知道已经有一个可以接受的答案,但想发布我正在使用的内容,以防它可以帮助任何人。我得到了类似cliphexmousewheel 事件的方向,但支持 Firefox。如果您正在执行诸如锁定滚动之类的操作并且无法获取当前滚动顶部,则这样做很有用。

See a live version here.

在此处查看实时版本。

$(window).on('mousewheel DOMMouseScroll', function (e) {

    var direction = (function () {

        var delta = (e.type === 'DOMMouseScroll' ?
                     e.originalEvent.detail * -40 :
                     e.originalEvent.wheelDelta);

        return delta > 0 ? 0 : 1;
    }());

    if(direction === 1) {
       // scroll down
    }
    if(direction === 0) {
       // scroll up
    }
});

回答by jherax

Scroll Event

滚动事件

The scroll eventbehaves oddly in FF (it is fired a lot of times because of the smoothness scrolling) but it works.

滚动事件会出现很奇怪的FF(它开了很多次,因为平滑滚动),但它的工作原理。

Note:The scrollevent actually is firedwhen dragging the scroll bar, using cursor keys or mousewheel.

注:滚动实际上事件被触发拖动滚动条时,使用光标键或鼠标滚轮。

//creates an element to print the scroll position
$("<p id='test'>").appendTo("body").css({
    padding: "5px 7px",
    background: "#e9e9e9",
    position: "fixed",
    bottom: "15px",
    left: "35px"
});

//binds the "scroll" event
$(window).scroll(function (e) {
    var target = e.currentTarget,
        self = $(target),
        scrollTop = window.pageYOffset || target.scrollTop,
        lastScrollTop = self.data("lastScrollTop") || 0,
        scrollHeight = target.scrollHeight || document.body.scrollHeight,
        scrollText = "";

    if (scrollTop > lastScrollTop) {
        scrollText = "<b>scroll down</b>";
    } else {
        scrollText = "<b>scroll up</b>";
    }

    $("#test").html(scrollText +
      "<br>innerHeight: " + self.innerHeight() +
      "<br>scrollHeight: " + scrollHeight +
      "<br>scrollTop: " + scrollTop +
      "<br>lastScrollTop: " + lastScrollTop);

    if (scrollHeight - scrollTop === self.innerHeight()) {
      console.log("? End of scroll");
    }

    //saves the current scrollTop
    self.data("lastScrollTop", scrollTop);
});


Wheel Event

车轮事件

You also may take a look at MDN, it exposes a great information about the Wheel Event.

您也可以查看 MDN,它公开了有关Wheel Event的大量信息

Note:The wheel event is fired only when using the mousewheel; cursor keys and dragging the scroll bar does not fire the event.

注意:wheel 事件只有在使用 mousewheel 时才会触发;光标键和拖动滚动条不会触发该事件。

I read the document and the example: Listening to this event across browser
and after some tests with FF, IE, chrome, safari, I ended up with this snippet:

我阅读了文档和示例:在浏览器中收听此事件,
并在使用 FF、IE、chrome、safari 进行了一些测试后,我最终得到了这个片段:

//creates an element to print the scroll position
$("<p id='test'>").appendTo("body").css({
    padding: "5px 7px",
    background: "#e9e9e9",
    position: "fixed",
    bottom: "15px",
    left: "15px"
});

//attach the "wheel" event if it is supported, otherwise "mousewheel" event is used
$("html").on(("onwheel" in document.createElement("div") ? "wheel" : "mousewheel"), function (e) {
    var evt = e.originalEvent || e;

    //this is what really matters
    var deltaY = evt.deltaY || (-1 / 40 * evt.wheelDelta), //wheel || mousewheel
        scrollTop = $(this).scrollTop() || $("body").scrollTop(), //fix safari
        scrollText = "";

    if (deltaY > 0) {
        scrollText = "<b>scroll down</b>";
    } else {
        scrollText = "<b>scroll up</b>";
    }

    //console.log("Event: ", evt);
    $("#test").html(scrollText +
      "<br>clientHeight: " + this.clientHeight +
      "<br>scrollHeight: " + this.scrollHeight +
      "<br>scrollTop: " + scrollTop +
      "<br>deltaY: " + deltaY);
});

回答by Yuri

In case you just want to know if you scroll up or down using a pointer device (mouse or track pad) you can use the deltaYproperty of the wheelevent.

如果您只想知道是使用指针设备(鼠标或触控板)向上还是向下滚动,您可以使用事件的deltaY属性wheel

$('.container').on('wheel', function(event) {
  if (event.originalEvent.deltaY > 0) {
    $('.result').append('Scrolled down!<br>');
  } else {
    $('.result').append('Scrolled up!<br>');
  }
});
.container {
  height: 200px;
  width: 400px;
  margin: 20px;
  border: 1px solid black;
  overflow-y: auto;
}
.content {
  height: 300px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="container">
  <div class="content">
    Scroll me!
  </div>
</div>

<div class="result">
  <p>Action:</p>
</div>

回答by J. Kovacevic

You can determin mousewhell direction.

您可以确定鼠井方向。

$(window).on('mousewheel DOMMouseScroll', function (e) {
    var delta = e.originalEvent.wheelDelta ? 
                   e.originalEvent.wheelDelta : -e.originalEvent.detail;

    if (delta >= 0) {
        console.log('scroll up');
    } else {
        console.log('scroll down');
    }
});

回答by GoreDefex

I have seen many version of good answers here but it seems some folks are having cross browser issues so this is my fix.

我在这里看到了许多版本的好答案,但似乎有些人遇到了跨浏览器问题,所以这是我的解决方案。

I have used this successfully to detect direction in FF, IE and Chrome ... I haven't tested it in safari as I use windows typically.

我已经成功地使用它来检测 FF、IE 和 Chrome 中的方向......我没有在 safari 中测试它,因为我通常使用 Windows。

$("html, body").bind({'mousewheel DOMMouseScroll onmousewheel touchmove scroll': 
    function(e) {
        if (e.target.id == 'el') return;
        e.preventDefault();
        e.stopPropagation();

        //Determine Direction
        if (e.originalEvent.wheelDelta && e.originalEvent.wheelDelta >= 0) {
            //Up
            alert("up");

        } else if (e.originalEvent.detail && e.originalEvent.detail <= 0) {
            //Up
            alert("up");

        } else {
            //Down
            alert("down");
        }
    }
});

Keep in mind I also use this to stop any scrolling so if you want scrolling to still occur you must remove the e.preventDefault(); e.stopPropagation();

请记住,我也使用它来停止任何滚动,因此如果您希望滚动仍然发生,您必须删除 e.preventDefault(); e.stopPropagation();

回答by Andrew Tibbetts

To ignore any snap / momentum / bounce back at the top and bottom of the page, here is a modified version of Josiah's accepted answer:

要忽略页面顶部和底部的任何快照/动量/反弹,以下是Josiah 已接受答案的修改版本:

var prevScrollTop = 0;
$(window).scroll(function(event){

    var scrollTop = $(this).scrollTop();

    if ( scrollTop < 0 ) {
        scrollTop = 0;
    }
    if ( scrollTop > $('body').height() - $(window).height() ) {
        scrollTop = $('body').height() - $(window).height();
    }

    if (scrollTop >= prevScrollTop && scrollTop) {
        // scrolling down
    } else {
        // scrolling up
    }

    prevScrollTop = scrollTop;
});