【问题标题】:How to detect scroll direction如何检测滚动方向
【发布时间】:2011-11-01 13:39:00
【问题描述】:

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

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

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

【问题讨论】:

标签: jquery scroll direction


【解决方案1】:

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

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

【讨论】:

  • 这个应该加到JQuery中
  • 应该是 e.originalEvent.wheelDelta
  • 请记住,从 jQuery 1.7 开始,on() 是附加事件处理程序的首选方式。
  • 其实也不是e.wheelDelta,也不是e.delta,而是e.originalEvent.wheelDelta
  • 谢谢,它可以节省时间@Rik de Vos
【解决方案2】:

以下示例将只听鼠标滚动,不听触摸或触控板滚动。

它使用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;
});

适用于所有浏览器。

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

【讨论】:

  • 刚刚在 IE9、Chrome 42 和 Firefox 37 上测试过。不错。我在 Mozilla b4 中遇到了这个问题。这解决了这个问题。
  • 我尝试了这个解决方案,但它在 FF (49.0.1) 上不起作用,但将“MozMousePixelScroll”添加到事件中修复了它。
【解决方案3】:

这个值得更新 - 现在我们有 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;
}
&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

现代浏览器的支持已经相当长一段时间了:

  • 铬 31+
  • 火狐17+
  • IE9+
  • Opera 18+
  • Safari 7+

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

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

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>

【讨论】:

  • 唯一的问题:在超过视口高度的网站上,该事件仅在滚轮停止滚动时触发,而不是在鼠标滚轮移动时触发。
  • 也许您可以详细说明您的意思。显然,无法通过鼠标转动进行平移,我知道的唯一与您的描述相近的问题是 IE 在转动鼠标滚轮和触发滚动事件之间存在轻微延迟。
【解决方案4】:

现有解决方案

此帖子和other stackoverflow article 可能有 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 上测试它

铬 42 (Win 7)

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

火狐 37 (Win 7)

  • 解决方案 1
    • 向上:每 1 个滚动条 20 个事件
    • 向下:每 1 个滚动 20 个事件
  • 解决方案 2
    • 向上:不工作
    • 向下:每 1 个滚动 1 个事件
  • 解决方案 3
    • 向上:不工作
    • 关闭:不工作

IE 11 (Win 8)

  • 解决方案 1
    • 向上:每 1 次滚动 10 个事件(副作用:最后发生向下滚动)
    • 向下:每 1 个滚动条 10 个事件
  • 解决方案 2
    • 向上:不工作
    • 关闭:不工作
  • 解决方案 3
    • 向上:不工作
    • 向下:每 1 个滚动 1 个事件

IE 10 (Win 7)

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

IE 9 (Win 7)

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

IE 8 (Win 7)

  • 解决方案 1
    • 向上:每 1 次滚动 2 个事件(副作用:最后发生向下滚动)
    • 向下:每 1 个滚动 2~4 个事件
  • 解决方案 2
    • 向上:不工作
    • 关闭:不工作
  • 解决方案 3
    • 向上:每 1 次滚动 1 个事件
    • 向下:每 1 次滚动 1 个事件

组合解决方案

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

在多浏览器测试中,我决定将Solution 3用于普通浏览器,Solution 1用于firefox和IE 11。

我推荐 this answer 检测 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');
            }
        });
    }

【讨论】:

  • 糟糕!我发现Mobile Chrome和Android默认浏览器只被方案1覆盖,所以方案1和方案3一起使用来覆盖各种浏览器会更好。
【解决方案5】:
$(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);
    });
});

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

【讨论】:

  • 你想要 scrollTop,而不是 offset.top
  • 1) 页面仍然会滚动 2) 如果 body 只有 600px 高并且您的浏览器窗口为 1000px,它不会检测到滚动
【解决方案6】:

Here is a sample 展示了一种简单的方法。脚本是:

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

#container 是您的 div id#target 只是为了看到它工作。在上升或下降时更改为您想要的。

编辑

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

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

电话只是:

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

【讨论】:

  • 当然可以,但是您必须将溢出设置为“自动”,而我将其设置为“隐藏”。如果我可以将溢出设置为“自动”或“滚动”,我就不会问这个问题 ;-)
【解决方案7】:
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();
            }   
    }
);

【讨论】:

  • 为什么在 evt.detail*(-40) 处乘以 -40
【解决方案8】:

您可以使用这个简单的插件将scrollUpscrollDown 添加到您的jQuery 中

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-20
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    相关资源
    最近更新 更多