检测是否在jQuery中手动触发滚动事件

时间:2013-12-23 06:11:51

标签: javascript jquery events scroll javascript-events

这个问题很久以前就已经问到了这个问题:

Detect jquery event trigger by user or call by code

但它从来没有得到最终的回答(或者我可能根本无法正确搜索)。

是否可以检测用户或jQuery scroll函数是否触发了animate事件?

我正在尝试阻止scroll事件在执行此类操作时触发自身:

$(document).scroll(function(){
    $("html").stop(true);
    var number = 400; //some other stuff is happening here
    clearTimeout(tout);
    tout = setTimeout(function(){
        if(top == $(document).scrollTop()){
            $("html").animate({
                scrollTop: (number),
                easing: "easeInQuad",
                duration: 110
            });
        }
    },120);
});

此代码似乎合适:

$('#scroller').scroll(function(e) {
    if (e.originalEvent) {
        console.log('scroll happen manual scroll');
    } else {
        console.log('scroll happen by call');
    }
});

但是originalEvent对象无法正确检测到动画触发器。

还有其他办法吗?

7 个答案:

答案 0 :(得分:20)

也许:animated选择器可以帮助您:

$('#scroller').scroll(function(e) {
    if ($(this).is(':animated')) {
        console.log('scroll happen by animate');
    } else if (e.originalEvent) {
        // scroll happen manual scroll
        console.log('scroll happen manual scroll');
    } else {
        // scroll happen by call
        console.log('scroll happen by call');
    }
});

Demo

答案 1 :(得分:6)

我不知道这对触摸屏设备的效果如何,但这对我来说至少适用于台式机

$(window).on('mousewheel', function(){
    //code that will only fire on manual scroll input
});

$(window).scroll(function(){
    //code that will fire on both mouse scroll and code based scroll
});

我不认为有一种方法可以只定位动画卷轴(接受的答案对我不起作用)。

更新:警告!

不幸的是,'mousewheel'似乎无法接受手动抓取滚动条并拖动它的用户或使用滚动条箭头按钮的用户:(

这仍适用于触摸屏设备,因为它们的滑动似乎算作鼠标滚动。对于桌面用户来说,这不是一个很好的解决方案。

答案 2 :(得分:2)

使用@Tony接受的答案和@DanielTonon的评论我提出了以下解决方案:

  var animatedScroll = false;
  var lastAnimatedScroll = false;
  $(window).scroll(function(event){
    lastAnimatedScroll = animatedScroll;
    animatedScroll = $('html, body').is(':animated');
  });

这似乎解决了提到的问题,即jquery删除.is(':animated')然后再滚动一个像素,这导致.is(':animated')以false结尾。通过存储.is(':animated')的倒数第二个版本,您可以(更)确定滚动是否为动画。

如果您想知道滚动是否已设置动画,只需检查lastAnimatedScroll变量。

我没有经过彻底的测试,但在许多页面刷新时都是正确的,所以我认为它运作良好。

答案 3 :(得分:1)

我建议首先创建一个javascript函数

// Attaching scroll event when document/window is loaded
    function OnFirstLoad() {
        if (document.attachEvent) {
            document.attachEvent('onscroll', scrollEvent);
        } else if (document.addEventListener) {
            document.addEventListener('scroll', scrollEvent, false);
        }

    }

然后,使用

        window.onload = OnFirstLoad;

或者

    $(document).ready(function () {
         OnFirstLoad();
    });

在此滚动事件中是一个函数

function scrollEvent(e) {
        var body = document.body,
             html = document.documentElement;

        var docHeight = Math.max(body.scrollHeight, body.offsetHeight,
                               html.clientHeight, html.scrollHeight, html.offsetHeight);
        var currentScroll = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
        // implement your logic according to requirement

    }

答案 4 :(得分:1)

尝试在本期中实现各种解决方案后,我想出了一种对我来说效果很好的方法。

我使用手动布尔值来确定动画是否正在运行:

var isRunningAnimation = false;

在进行动画制作之前将其设置为true,并在jQuery false回调函数中将其设置为animate

  isRunningAnimation = true;

  $('html').animate({
    scrollLeft: 100,
    scrollTop:  100
  }, 400, 'swing', function() {
    isRunningAnimation = false;
  });

,然后在滚动侦听器中检查该布尔值:

$('scroll', function() {
  if (!isRunningAnimation) {
    // If we made it to here, the animation isn't running
  }
});

从技术上讲,当然,如果用户决定在动画过程中手动滚动,则也不会触发滚动逻辑,但这似乎足以应付边缘情况。

答案 5 :(得分:0)

如果要与jquery选择器绑定并检查事件

$('#div.class').bind('scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove', function (e) {
    if (e.which > 0 || e.type == "mousedown" || e.type == "mousewheel" || e.type == "touchmove") {
      // any code
    }
})

答案 6 :(得分:0)

jQuery(document).on('click', 'p.questions__text a[data-clickid="delay_next_delivery"]', function(ele){
    if(ele.originalEvent.isTrusted){
        // human
    } else {
        // non human
    }
});