最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jQuery: The 'body' element is activating the scroll event twice - Stack Overflow

programmeradmin0浏览0评论

I've implemented an animation for my photo blog. I still have big problem because the 'body' element is activating the animation twice.

I think the problem stems from the $('body').animate. Because I think that when the body is animating, the scroll event would be activated again and thus triggering the event twice.

The problem of my code is scrolling the page up. When I scroll the page upwards. The scrollAnimatePrev will trigger and then $('body') element will animate itself. After the animation the animating variable is set to false. But the $('body') element triggers the scroll event because I guess when I set the scrollTop the scroll event is triggered. So once again currentPos is set to the $(window).scrollTop() then currentPos > previousPos returns true and !animating returns true so it will trigger the scrollAnimate.

Now I want to fix this. How?

    $(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;
                }
            )
        }
    })

I've implemented an animation for my photo blog. I still have big problem because the 'body' element is activating the animation twice.

I think the problem stems from the $('body').animate. Because I think that when the body is animating, the scroll event would be activated again and thus triggering the event twice.

The problem of my code is scrolling the page up. When I scroll the page upwards. The scrollAnimatePrev will trigger and then $('body') element will animate itself. After the animation the animating variable is set to false. But the $('body') element triggers the scroll event because I guess when I set the scrollTop the scroll event is triggered. So once again currentPos is set to the $(window).scrollTop() then currentPos > previousPos returns true and !animating returns true so it will trigger the scrollAnimate.

Now I want to fix this. How?

    $(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;
                }
            )
        }
    })
Share Improve this question asked May 5, 2009 at 4:39 Keira NighlyKeira Nighly 15.5k8 gold badges30 silver badges28 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 3

I think it might be firing that callback twice. I had a similar problem recently.

I had something similiar to

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

It was calling my doSomethingOnceOnly() twice, and I thought it must have been the dual selectors in the $ argument. I simply made it 2 different selectors and it worked fine. So like this

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

Using a flag to control the trigger did the trick for me.

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

评论列表(0)

  1. 暂无评论