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

我在找这样的东西:

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

什么好主意吗?

469990 次浏览

检查当前的scrollTop和之前的scrollTop

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

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

下面是避免任何全局变量的方法(这里有小提琴):

(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
var tempScrollTop, currentScrollTop = 0;


$(window).scroll(function(){


currentScrollTop = $("#div").scrollTop();


if (tempScrollTop > currentScrollTop ) {
// upscroll code
}
else if (tempScrollTop < currentScrollTop ){
// downscroll code
}


tempScrollTop = currentScrollTop;
}

或使用mousewheel扩展,参见在这里

你可以这样做,而不必跟踪之前的滚动顶部,因为所有其他的例子都要求:

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

我不是这方面的专家,所以可以随意进一步研究,但似乎当你使用$(element).scroll时,被监听的事件是一个“滚动”事件。

但是如果你使用bind专门监听mousewheel事件,回调的事件参数的originalEvent属性包含不同的信息。该信息的一部分是wheelDelta。如果是正数,你就向上移动鼠标滚轮。如果是负的,鼠标滚轮就向下移动了。

我的猜测是mousewheel事件将在鼠标滚轮转动时触发,即使页面没有滚动;在这种情况下,'scroll'事件可能不会被触发。如果你愿意,你可以在回调的底部调用event.preventDefault()来防止页面滚动,这样你就可以将鼠标滚轮事件用于页面滚动之外的其他事情,比如某种类型的缩放功能。

在滚动的元素的.data ()中存储一个增量,然后你将能够测试滚动到达顶部的次数。

在元素的.data()中,您可以存储JSON和测试值来启动事件

{ top : 1,
first_top_event: function(){ ...},
second_top_event: function(){ ...},
third_top_event: function(){ ...},
scroll_down_event1: function(){ ...},
scroll_down_event2: function(){ ...}
}

滚动事件

滚动事件在FF中表现奇怪(由于平滑滚动,它被触发了很多次),但它是有效的。

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

//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);
});

轮事件

你也可以看看MDN,它揭示了关于车轮事件
的大量信息

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

我读了文档和例子:跨浏览器监听此事件
在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);
});

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

我已经成功地使用这个方法在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");
}
}
});

请记住,我还使用它来停止任何滚动,所以如果你想要滚动仍然发生,你必须删除e.preventDefault(); e.stopPropagation();

我知道已经有了一个公认的答案,但我想张贴我正在使用的,以防它可以帮助任何人。我得到的方向像cliphex与鼠标滚轮事件,但支持Firefox。这样做很有用,以防你在做一些事情,比如锁定滚动,无法获得当前滚动顶部。

查看活动版本在这里

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

为了忽略页面顶部和底部的任何snap / momentum / bounce back,这里是约西亚接受的答案的修改版本:

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

现有的解决方案

这篇文章中可能有3解决方案其他的答案

解决方案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;
});

解决方案2

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

解决方案3

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

多浏览器测试

我无法在Safari上测试它

chrome 42 (Win 7)

    <李>解决方案1
    • 向上:每次滚动1个事件
    • 向下:每滚动1个事件
    <李>解决方案2
    • 向上:不工作
    • 向下:不工作
    <李>解决方案3
    • 向上:每次滚动1个事件
    • 向下:每滚动1个事件

Firefox 37 (win7)

    <李>解决方案1
    • 向上:每次滚动20个事件
    • 向下:每次滚动20个事件
    <李>解决方案2
    • 向上:不工作
    • 向下:每滚动1个事件
    <李>解决方案3
    • 向上:不工作
    • 向下:不工作

IE 11 (win8)

    <李>解决方案1
    • 向上:每一次滚动10个事件(副作用:最后出现向下滚动)
    • 向下:每次滚动10个事件
    <李>解决方案2
    • 向上:不工作
    • 向下:不工作
    <李>解决方案3
    • 向上:不工作
    • 向下:每滚动1个事件

IE 10 (win7)

    <李>解决方案1
    • 向上:每次滚动1个事件
    • 向下:每滚动1个事件
    <李>解决方案2
    • 向上:不工作
    • 向下:不工作
    <李>解决方案3
    • 向上:每次滚动1个事件
    • 向下:每滚动1个事件

IE 9 (win7)

    <李>解决方案1
    • 向上:每次滚动1个事件
    • 向下:每滚动1个事件
    <李>解决方案2
    • 向上:不工作
    • 向下:不工作
    <李>解决方案3
    • 向上:每次滚动1个事件
    • 向下:每滚动1个事件

IE 8 (win7)

    <李>解决方案1
    • 向上:每一次滚动2个事件(副作用:最后出现向下滚动)
    • 向下:每一次滚动2~4个事件
    <李>解决方案2
    • 向上:不工作
    • 向下:不工作
    <李>解决方案3
    • 向上:每次滚动1个事件
    • 向下:每滚动1个事件

联合解决方案

我检查了IE 11和IE 8的副作用是来自if else语句。因此,我将其替换为if else if语句,如下所示。

从多浏览器测试中,我决定在普通浏览器中使用解决方案3,在firefox和IE 11中使用解决方案1

我引用这个答案来检测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.$1);
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');
}
});
}

对于用户何时从页面顶部滚动以及何时返回到页面顶部,这是简单而容易的检测。

$(window).scroll(function() {
if($(window).scrollTop() > 0) {
// User has scrolled
} else {
// User at top of page
}
});

这是在用户结束滚动时检测方向的最佳解决方案。

var currentScrollTop = 0 ;


$(window).bind('scroll', function () {


scrollTop = $(this).scrollTop();


clearTimeout($.data(this, 'scrollTimer'));
$.data(this, 'scrollTimer', setTimeout(function() {


if(scrollTop > currentScrollTop){
// downscroll code
$('.mfb-component--bl').addClass('mfbHide');
}else{
// upscroll code
$('.mfb-component--bl').removeClass('mfbHide');
}
currentScrollTop = scrollTop;


}, 250));


});

如果你只是想知道你是使用指针设备(鼠标或跟踪板)向上滚动还是向下滚动,你可以使用wheel事件的δy属性。

$('.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>

你可以确定鼠标的方向。

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

保持超级简单:

jQuery事件监听器

$(window).on('wheel', function(){
whichDirection(event);
});

香草JavaScript事件监听器

if(window.addEventListener){
addEventListener('wheel', whichDirection, false);
} else if (window.attachEvent) {
attachEvent('wheel', whichDirection, false);
}

功能不变:

function whichDirection(event){
console.log(event + ' WheelEvent has all kinds of good stuff to work with');
var scrollDirection = event.deltaY;
if(scrollDirection === 1){
console.log('meet me at the club, going down', scrollDirection);
} else if(scrollDirection === -1) {
console.log('Going up, on a tuesday', scrollDirection);
}
}

我写了一篇更深入的文章这里 < / p >

您可以同时使用滚动和鼠标滚轮选项来跟踪上下移动一次。

 $('body').bind('scroll mousewheel', function(event) {


if (event.originalEvent.wheelDelta >= 0) {
console.log('moving down');
}
else {
console.log('moving up');
}
});

你也可以用window代替body。

使用这个来找到滚动方向。这只是为了找到垂直滚动的方向。支持所有跨浏览器。

    var scrollableElement = document.getElementById('scrollableElement');


scrollableElement.addEventListener('wheel', findScrollDirectionOtherBrowsers);


function findScrollDirectionOtherBrowsers(event){
var delta;


if (event.wheelDelta){
delta = event.wheelDelta;
}else{
delta = -1 * event.deltaY;
}


if (delta < 0){
console.log("DOWN");
}else if (delta > 0){
console.log("UP");
}


}

使用实例

你应该试试这个

var scrl
$(window).scroll(function(){
if($(window).scrollTop() < scrl){
//some code while previous scroll
}else{
if($(window).scrollTop() > 200){
//scroll while downward
}else{//scroll while downward after some specific height
}
}
scrl = $(window).scrollTop();
});

为什么没有人在滚动时使用jQuery返回的event对象?

$window.on('scroll', function (event) {
console.group('Scroll');
console.info('Scroll event:', event);
console.info('Position:', this.pageYOffset);
console.info('Direction:', event.originalEvent.dir); // Here is the direction
console.groupEnd();
});

我正在使用chromium,我没有检查其他浏览器是否有dir属性。

这段代码在IE, Firefox, Opera和Chrome中工作良好:

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

“轮mousewheel”和属性δy必须在bind ()函数中使用。

记住:出于安全考虑,你的用户必须更新他们的系统和浏览器。2018年,“我有ie7”的借口是一派胡言。我们必须教育用户。

祝你有愉快的一天。

更新2021-04-07

Bobort在注释(谢谢!)中指出了在轮的文档中添加的新注释:

不要混淆车轮事件和滚动事件。轮事件的默认动作是特定于实现的,并不一定会分派滚动事件。即使它这样做,wheel事件中的Delta *值不一定反映内容的滚动方向.;因此,不要依赖wheel事件的delta*属性来获得滚动方向。相反,在scroll事件中检测目标的scrollLeft和scrollTop的值变化。

但是,文档中给出的示例使用delta来缩放,这意味着向上滚动用于缩小,向下滚动用于放大。

下面的代码在不同的浏览器中都可以用于检测方向,但考虑到这一点,请自行承担使用风险。

原来的答案

由于v3上的bind已弃用 ("被on"取代)和现在支持wheel,忘记wheelDelta:

$(window).on('wheel', function(e) {
if (e.originalEvent.deltaY > 0) {
console.log('down');
} else if (e.originalEvent.deltaY < 0) {
console.log('up');
} else if (e.originalEvent.deltaX > 0) {
console.log('right');
} else if (e.originalEvent.deltaX < 0) {
console.log('left');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 style="white-space:nowrap;overflow:scroll">
🚂🚃🚃🚂🚃🚃🚃🚂🚃🚃🚂🚃🚃🚃🚂🚃<br/>
🚎🚌🚌🚌🚎🚌🚌🚎🚌🚌🚌🚎🚌🚌🚎🚌<br/>
🚂🚃🚃🚂🚃🚃🚃🚂🚃🚃🚂🚃🚃🚃🚂🚃<br/>
🚎🚌🚌🚌🚎🚌🚌🚎🚌🚌🚌🚎🚌🚌🚎🚌<br/>
🚂🚃🚃🚂🚃🚃🚃🚂🚃🚃🚂🚃🚃🚃🚂🚃<br/>
🚎🚌🚌🚌🚎🚌🚌🚎🚌🚌🚌🚎🚌🚌🚎🚌<br/>
</h1>

wheel事件的MDN浏览器兼容性(2019-03-18):

车轮事件的兼容性

我有问题弹性滚动(滚动反弹,橡皮筋)。 如果接近页面顶部,忽略下滚动事件对我有用

var position = $(window).scrollTop();
$(window).scroll(function () {
var scroll = $(window).scrollTop();
var downScroll = scroll > position;
var closeToTop = -120 < scroll && scroll < 120;
if (downScroll && !closeToTop) {
// scrolled down and not to close to top (to avoid Ipad elastic scroll-problems)
$('.top-container').slideUp('fast');
$('.main-header').addClass('padding-top');
} else {
// scrolled up
$('.top-container').slideDown('fast');
$('.main-header').removeClass('padding-top');
}
position = scroll;
});

你也可以使用这个

$(document).ready(function(){


var currentscroll_position = $(window).scrollTop();
$(window).on('scroll', function(){
Get_page_scroll_direction();
});


function Get_page_scroll_direction(){
var running_scroll_position = $(window).scrollTop();
if(running_scroll_position > currentscroll_position) {
      

$('.direction_value').text('Scrolling Down Scripts');


} else {
       

$('.direction_value').text('Scrolling Up Scripts');


}
currentscroll_position = running_scroll_position;
}


});
.direction_value{
position: fixed;
height: 30px;
background-color: #333;
color: #fff;
text-align: center;
z-index: 99;
left: 0;
top: 0;
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


<div class="direction_value">
</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi ducimus expedita facilis architecto fugiat veniam natus suscipit amet beatae atque, enim recusandae quos, magnam, perferendis accusamus cumque nemo modi unde!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi ducimus expedita facilis architecto fugiat veniam natus suscipit amet beatae atque, enim recusandae quos, magnam, perferendis accusamus cumque nemo modi unde!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi ducimus expedita facilis architecto fugiat veniam natus suscipit amet beatae atque, enim recusandae quos, magnam, perferendis accusamus cumque nemo modi unde!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi ducimus expedita facilis architecto fugiat veniam natus suscipit amet beatae atque, enim recusandae quos, magnam, perferendis accusamus cumque nemo modi unde!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi ducimus expedita facilis architecto fugiat veniam natus suscipit amet beatae atque, enim recusandae quos, magnam, perferendis accusamus cumque nemo modi unde!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi ducimus expedita facilis architecto fugiat veniam natus suscipit amet beatae atque, enim recusandae quos, magnam, perferendis accusamus cumque nemo modi unde!</p>

这适用于所有pc或手机浏览器,扩展顶部的答案。可以构建一个更复杂的事件对象窗口["scroll_evt"],然后在handleScroll()函数中调用它。如果经过了一定的延迟或传递了一定的增量以消除一些不需要的触发器,则该函数将触发2个并发条件。

window["scroll_evt"]={"delta":0,"delay":0,"direction":0,"time":Date.now(),"pos":$(window).scrollTop(),"min_delta":120,"min_delay":10};
$(window).scroll(function() {


var currentScroll = $(this).scrollTop();
var currentTime = Date.now();
var boolRun=(window["scroll_evt"]["min_delay"]>0)?(Math.abs(currentTime - window["scroll_evt"]["time"])>window["scroll_evt"]["min_delay"]):false;
boolRun = boolRun && ((window["scroll_evt"]["min_delta"]>0)?(Math.abs(currentScroll - window["scroll_evt"]["pos"])>window["scroll_evt"]["min_delta"]):false);
if(boolRun){
window["scroll_evt"]["delta"] = currentScroll - window["scroll_evt"]["pos"];
window["scroll_evt"]["direction"] = window["scroll_evt"]["delta"]>0?'down':'up';
window["scroll_evt"]["delay"] =currentTime - window["scroll_evt"]["time"];//in milisecs!!!
window["scroll_evt"]["pos"] = currentScroll;
window["scroll_evt"]["time"] = currentTime;
handleScroll();
}
});




function handleScroll(){
event.stopPropagation();
//alert(window["scroll_evt"]["direction"]);
console.log(window["scroll_evt"]);
}