views:

1021

answers:

2

Hi guys, 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;
       }
      )
     }
    })
+1  A: 

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 of 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(); );
alex
Yes, how did you fix the problem.. I have an ugly hack, it's a setTimeout.. I want this to be generic and dont rely on timing...
Keira Nighly
I think I stopped chaining the animate(); I'll edit my answer
alex
IC, okay.. Thanks Alex
Keira Nighly
Did that work for you ?
alex
A: 

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