在jquery scrollTop动画完成后滚动显示

时间:2013-10-18 08:58:46

标签: javascript jquery

为什么在scrollTop动画触发complete回调后会调用另一个滚动事件

点击处理程序:

var lock = false;

$('#id').click(function(event) {
    var pos;
    if (lock) {
        return;
    }
    lock = true;
    pos = 150;

    console.log("jump start");

    $(jQuery.browser.webkit ? "body": "html").animate({ scrollTop: pos }, 150, function () {
        lock = false;
        console.log("jump end");
    });
});

Scroll Handler:

$(window).scroll(function (e) {
    console.log("scrolling");

    if (!lock){
        alert('1');
    }
});

日志:

jump start
scrolling
jump end
scrolling

demo on jsfiddle

2 个答案:

答案 0 :(得分:11)

<强>背景

jQuery scrollTop()使用scrollTo()这是一个fire and forget事件。滚动没有停止的事件。滚动事件从scrollTo带外发生。 scrollTo表示'开始滚动',滚动事件表示'滚动(某个位置)'。 scrollTo只是启动滚动的开始,它不保证滚动返回时完成。因此,jQuery动画在最终滚动之前完成(甚至可以备份多个滚动)。替代方案是jQuery等待滚动的位置是它所要求的(根据我的解决方案),但它不会这样做

如果有一个我们可以指出描述这个的规范会很好,但它只是没有规范的<0> dom元素之一, see here 。我认为它的工作方式是有道理的,这就是为什么所有浏览器似乎都是这样实现的。

为什么会发生这种情况

以下内容出现在动画的最后一个卷轴上:

  1. jquery:'窗口请滚动最后一点'
  2. 窗口:'我从jquery收到此消息滚动我现在将开始'
  3. jquery:'哇哇我完成了动画,我将完成'
  4. 您的代码:lock = false;console.log("jump end");
  5. 窗口:'我已滚动'调用滚动事件处理程序。'
  6. 您的代码:$(window).scroll(function (e) {'为什么会发生这种情况?'
  7. 正如您所见,jquery不会在完成动画之前等待动画的最后滚动步骤(继续执行步骤4)。部分原因是因为滚动没有停止的事件,部分原因是因为jquery不等待滚动位置到达请求的位置。我们可以检测到我们何时到达目的地位置,如下所述。

    <强>解决方案

    滚动完成时没有停止的事件。的 See here 即可。有意义的是没有停止的事件,因为用户可以在任何点再次开始滚动,因此滚动没有真正停止的点 - 用户可能只是暂停了几分之一秒。

    用户滚动:对于用户滚动,正常的方法是等待一段时间来查看滚动是否完整,如引用问题的答案中所述(请记住用户可以再次开始滚动)。

    scrollTop :但是,由于我们知道滚动到的位置,我们可以做得更好。

    参见 this fiddle.

    它的关键在于,既然我们知道滚动到哪里,我们就可以存储该位置。当我们到达那个位置时,我们知道我们已经完成了。

    输出现在是:

    jump start
    scroll animation
    jump end
    

    代码是(请注意,这是基于您的小提琴而不是编辑问题中的代码):

    var scrollingTo = 0;
    $('#id').click(function(event) {    
        if (scrollingTo) {
            return;
        }        
        console.log("jump start");
        scrollingTo = 150;
        $(jQuery.browser.webkit ? "body": "html").animate({ scrollTop: scrollingTo }, 150, function () {                
        });
    });
    
    function handleScroll()
    {    
        if( scrollingTo !== 0  && $(window).scrollTop() == scrollingTo)
        {
            scrollingTo = 0;
            console.log("jump end");    
        }
    }
    
    $(window).scroll(function (e) {    
        if (!scrollingTo){
            console.log('user scroll');
        } else {
            console.log("scroll animation");
        }
        handleScroll();
    });
    

答案 1 :(得分:0)

我相信在动画结束并调用回调函数时,事件还没有到达window,所以它没有被重新调用,它还没有被解雇。 / p>