jQuery:'body'元素触发了滚动事件两次

3
我已经为我的照片博客实现了一个动画。但仍有一个大问题,因为“body”元素会使动画运行两次。
我想问题出在$('body').animate上。当body正在进行动画时,滚动事件会被再次激活,从而触发两次事件。
我的代码的问题是向上滚动页面。当我向上滚动页面时,scrollAnimatePrev会被触发,然后$('body')元素会开始运动。动画结束后,animating变量被设置为false。但是$('body')元素会再次触发滚动事件,因为当我设置scrollTop时,滚动事件就会被触发。所以当前位置currentPos再次被设置为$(window).scrollTop(),然后currentPos > previousPos返回true并且 !animating返回true,所以它将触发scrollAnimate。
现在我想修复这个问题,怎么办?
    $(function() {
        var record = 0;
        var imgHeight = $(".images").height();
        var offset = $(".images").eq(0).offset();
        var offsetHeight = offset.top;
        var previousPos = $(window).scrollTop();
        var animating = false;
        var state = 0;
        $(window).scroll(function() {
            var currentPos = $(window).scrollTop();
            console.log(currentPos);
            if(currentPos > previousPos && !animating) {
                record++;
                scrollAnimate(record, imgHeight, offsetHeight);
                animating = true;
            } else if (currentPos < previousPos && !animating) {
                record--
                scrollAnimatePrev(record, imgHeight, offsetHeight);
                animating = true;
            }
            previousPos = currentPos;
            console.log(previousPos)
        })


        function scrollAnimate(record, imgHeight, offsetHeight) {
            $('body').animate(
                {scrollTop: (parseInt(offsetHeight) * (record+1)) + (parseInt(imgHeight) * record)},
                1000,
                "easeInOutQuart"                    
            )
            .animate(
                {scrollTop: (parseInt(offsetHeight) * (record)) + (parseInt(imgHeight) * (record))},
                1000,
                "easeOutBounce",
                function() {
                    animating = false;
                }
            )
        }

        function scrollAnimatePrev(record, imgHeight, offsetHeight) {
            $('body').animate(
                {scrollTop: ((parseInt(imgHeight) * record) + (parseInt(offsetHeight) * record)) - offsetHeight},
                1000,
                "easeInOutQuart"
            )
            .animate(
                {scrollTop: ((parseInt(imgHeight) * record) + (parseInt(offsetHeight) * record))},
                1000,
                "easeOutBounce",
                function() {
                    animating = false;
                }
            )
        }
    })
2个回答

3
我认为可能会触发两次回调函数。我最近遇到了类似的问题。
我之前也遇到过类似的情况。
$('#id, #id2').animate({width: '200px'}, 100, function() { doSomethingOnceOnly(); })

我的doSomethingOnceOnly()被调用了两次,我认为可能是$参数中的双重选择器。我只需将其更改为2个不同的选择器,就可以正常工作。像这样:

$('#id').animate({width: '200px'}, 100);
$('#id2').animate({width: '200px'}, 100, function() { doSomethingOnceOnly(); );

是的,你是怎么解决这个问题的?我有一个丑陋的hack,它是一个setTimeout.. 我希望这个方法是通用的,不依赖于时间... - Keira Nighly
我想我已经停止使用 animate() 链接了,我将编辑我的答案。 - alex

2

对我来说,使用标志来控制触发器是一个有效的解决方法。

var targetOffset = 0;
var allow_trigger = true;
$('html,body').animate({scrollTop: targetOffset}, 'slow', function() {
    if (allow_trigger) {
        allow_trigger = false;
        doSomethingOnlyOnce();
    }
});

谢谢,这个方法非常完美地解决了我的问题。我想要在表单中滚动到第一个错误并将其突出显示,但是它却突出显示了两次...我想知道为什么所有的滚动效果都使用$('html,body')规则。你总是有一个html和body。为什么要“双重覆盖”? - armyofda12mnkeys

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接