如何区分手动滚动(通过鼠标滚轮/滚动条)和 Javascript/jQuery 滚动?

Posted

技术标签:

【中文标题】如何区分手动滚动(通过鼠标滚轮/滚动条)和 Javascript/jQuery 滚动?【英文标题】:How can I differentiate a manual scroll (via mousewheel/scrollbar) from a Javascript/jQuery scroll? 【发布时间】:2011-02-19 13:13:30 【问题描述】:

更新:

这是一个 jsbin example 演示问题。

更新 2: 这里是the fixed version 感谢fudgey。


基本上,我有以下 javascript 将窗口滚动到页面上的锚点:

 // get anchors with href's that start with "#"
 $("a[href^=#]").live("click", function()
     var target = $($(this).attr("href"));
     // if the target exists: scroll to it...
     if(target[0])
         // If the page isn't long enough to scroll to the target's position
         // we want to scroll as much as we can. This part prevents a sudden 
         // stop when window.scrollTop reaches its maximum.
         var y = Math.min(target.offset().top, $(document).height() - $(window).height());
         // also, don't try to scroll to a negative value...
         y=Math.max(y,0);
         // OK, you can scroll now...
         $("html,body").stop().animate( "scrollTop": y , 1000);
     
     return false;
 );

它工作得很好......直到我手动尝试滚动窗口。当滚动条或鼠标滚轮滚动时,我需要停止当前的滚动动画……但我不知道该怎么做。

这大概是我的出发点……

$(window).scroll(e)
    if(IsManuallyScrolled(e))
        $("html,body").stop();
    
 

...但我不确定如何编写 IsManuallyScrolled 函数。我已经在 Google Chrome 的控制台和 AFAIK 中检查了 eevent 对象),无法区分手动滚动和 jQuery 的 animate() 滚动。

如何区分 手动 滚动和通过 jQuery 的 $.fn.animate 函数调用的滚动?

【问题讨论】:

【参考方案1】:

试试这个功能:

$('body,html').bind('scroll mousedown wheel DOMMouseScroll mousewheel keyup', function(e)
 if ( e.which > 0 || e.type == "mousedown" || e.type == "mousewheel")
  $("html,body").stop();
 
)

另外,你看到this tutorial了吗?

更新:现代浏览器现在使用 "wheel" 作为事件,所以我将它包含在上面的代码中。

【讨论】:

谢谢!不,我没有看到教程,也谢谢你。这是更新后的JSBin example 与您的修复 哦,为什么要使用 DOMMouseScroll?是否“滚动”!==“DomMouseScroll”? DOMMouseScroll 仅适用于 Firefox(参考:quirksmode.org/dom/events/scroll.html) 更新:在绑定中添加了“wheel”事件。 对于触摸屏设备,您需要将touchstart 添加到您的事件列表中,并在事件本身中检查它... || e.type == 'touchstart'【参考方案2】:

几天前我遇到了同样的问题。如果你想获得这个结果,你不应该使用 jquery 的 animate 函数,你必须使用轮询函数来模拟动画。 我制作了这个类,它应该在调用 ScrollDown.slow() 时提供平滑的向下滚动。

ScrollDown.current=$(window).scrollTop();
ScrollDown.lastValue;
ScrollDown.lastType;
ScrollDown.enabled=true;
ScrollDown.custom=function(value,rate)  //let's say value==='bottom' and rate=10
    if(value==='bottom')
        value=$(document).height()-$(window).height();
    
    ScrollDown.current=$(window).scrollTop();
    ScrollDown.lastValue=value;
    (function poll()
        setTimeout(function()
            var prev=$(window).scrollTop();  //This is the critical part
            /*I'm saving again the scroll position of the window, remember
            10 ms have passed since the polling has started
            At this rate, if the user will scroll up for down pre!==ScrollDown.current
            And that means I have to stop scrolling.*/
            ScrollDown.current++; //increasing the scroll variable so that it keeps scrolling
            $(window).scrollTop(ScrollDown.current);
            if(ScrollDown.current<ScrollDown.lastValue && ScrollDown.enabled)  
            //ScrollDown.current<ScrollDown.lastValue basically checks if it's reached the bottom
                if(prev!==ScrollDown.current-1)
                /*I'm checking if the user 
                scrolled up or down while the polling has been going on, 
                if the user scrolls up then prev<ScrollDown.current-1, 
                if the user scrolls down then prev>ScrollDown.current-1 
                and at the next poll() the scrolling will stop 
                because ScrollDown.enabled will bet set to false by ScrollDown.stop()*/
                    ScrollDown.stop();
                
                poll();
            
        ,rate);
    )();
;

ScrollDown.stop=function()
    ScrollDown.enabled=false;
;

ScrollDown.continue=function()
    ScrollDown.enabled=true;
    switch (ScrollDown.lastType)
        case "fast":
            ScrollDown.fast(ScrollDown.lastValue);
            break;
        case "normal":
            ScrollDown.normal(ScrollDown.lastValue);
            break;
        case "slow":
            ScrollDown.slow(ScrollDown.lastValue);
            break;
    
;

ScrollDown.fast=function(value)
    if(!ScrollDown.enabled)
        ScrollDown.continue();
    else
        ScrollDown.lastType='fast';
        ScrollDown.custom(value,1);
    
;
ScrollDown.normal=function(value)
    if(!ScrollDown.enabled)
        ScrollDown.continue();
    else
        ScrollDown.lastType='normal';
        ScrollDown.custom(value,10);
    
;
ScrollDown.slow=function(value)
    if(!ScrollDown.enabled)
        ScrollDown.continue();
    else
        ScrollDown.lastType='slow';
        ScrollDown.custom(value,50);
    
;
function ScrollDown()

因此,如果您要调用 ScrollDown.slow('bottom'),它将开始缓慢滚动,直到到达页面底部,除非您手动向上或向下滚动,然后它会停止。

【讨论】:

【参考方案3】:

您可以设置一个变量来指示您对 animate 的调用处于活动状态,然后在滚动处理程序中检查该变量。

window.IsAutoScrolling = true;
$("html,body").stop().animate( "scrollTop": y , 1000);
// Do something to set IsAutoScrolling = false, when the animation is done.

$(window).scroll(e)  
if(!window.IsAutoScrolling)  
    $("html,body").stop();  
  

【讨论】:

这行不通,因为 window.IsAutoScrolling 在滚动停止之前始终为真......此时我们不再关心窗口是否自动滚动。问题是检测在动画滚动期间调用滚动的内容; jquery 或用户。

以上是关于如何区分手动滚动(通过鼠标滚轮/滚动条)和 Javascript/jQuery 滚动?的主要内容,如果未能解决你的问题,请参考以下文章

删除 HTML 滚动条但允许鼠标滚轮滚动 [重复]

如何让VB6代码编辑器垂直滚动条随鼠标滚轮滚动

网页不能用鼠标滚轮控制滚动条 我鼠标滚轮上下滚动。。但网页没反应。这是怎么回事。。怎么修复。。

使用 jQuery 检查没有滚动条的鼠标滚轮事件

echarts区域缩放(鼠标滚轮滚动条拉选框)

带有硒网络驱动程序的鼠标滚轮,在没有滚动条的元素上?