Finnb
Finnb

Reputation: 65

Run .animate() once after scroll trigger

I have a div I'd like to animate once after a certain distance has been reached between a trigger div and the top of the window, but when within a .scroll() function the animation is continually triggered as you scroll.

This below code works fine:

$(window).scroll(function(){
   var a = $('.intro-text').offset().top;
   console.log(a);

   if ( a > 100 ) {
     $('.hide-me').fadeOut();
   } else if ( a < 100 ) {
     $('.hide-me').fadeIn();
   }

});

But if I change it to .animate(), it's continually queued up and takes forever to run:

$(window).scroll(function(){
   var a = $('.intro-text').offset().top;
   console.log(a);

   if ( a > 100 ) {

     $('.hide-me').animate({
       left: -200
     }, 1000);

   } else if ( a < 100 ) {

     $('.hide-me').animate({
       left: 0
     }, 1000);

   }

});

My coding skills aren't the best, but I'd like it to learn if there's a function within jQuery / pure javascript before going into any external libraries or plugins. Any help would be much appreciated, thanks.

Upvotes: 0

Views: 1177

Answers (2)

Nadir Laskar
Nadir Laskar

Reputation: 4150

Create a scroll object and save two flags fadeIn and fadeOut

var scroll = {
          fadeIn: false,
          fadeOut: false
};

Explanation

Inside your scroll event there are two conditions a>100 and a<100

So, once one of the condition is true it goes inside and check if the flag is set before triggering the animation and then sets flag of the animation done to true and clears the other flag.

For Example:

 if (a > 100) {
    if (!scroll.fadeOut) {
      $('.hide-me').fadeOut();
      scroll.fadeOut = true;
      scroll.fadeIn = false;
    }
  }

In the above code

It checks if scroll.fadeOut is not set then

It does the animation

 $('.hide-me').fadeOut();

and sets the flags

 scroll.fadeOut = true;
 scroll.fadeIn = false;

This will not allow this animation to be executed again until the second one is triggered and its clears the flag.

Full JS

var scroll = {
      fadeIn: false,
      fadeOut: false
};

$(window).scroll(function() {
  var a = $('.intro-text').offset().top;
  console.log(a);

  if (a > 100) {
    if (!scroll.fadeOut) {
      $('.hide-me').fadeOut();
      scroll.fadeOut = true;
      scroll.fadeIn = false;
    }
  } else if (a < 100) {
    if (!scroll.fadeIn) {
      $('.hide-me').fadeIn();
      scroll.fadeIn = true;
      scroll.fadeOut = false;
    }
  }

});

UPDATE

var scroll = {
  fadeIn: false,
  fadeOut: false
};

$(window).scroll(function() {
  var a = $('.intro-text').offset().top;
  console.log(a);

  if (a > 100) {
    if (!scroll.fadeOut) {
      $('.hide-me').animate({
        left: -200
      }, 1000);
      scroll.fadeOut = true;
      scroll.fadeIn = false;
    }
  } else if (a < 100) {
    if (!scroll.fadeIn) {
      $('.hide-me').animate({
        left: 0
      }, 1000);
      scroll.fadeIn = true;
      scroll.fadeOut = false;
    }
  }

});

Upvotes: 1

palaѕн
palaѕн

Reputation: 73906

In these scenarios you can use jquery .stop([clearQueue],[jumpToEnd]) method like:

function debounce(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this,
      args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
};

$(window).scroll(function() {
  debounce(function() {
    var a = $('.intro-text').offset().top;
    console.log(a);
    if (a > 100) {
      $('.hide-me').stop(true, true).animate({
        left: -200
      }, 1000);
    } else if (a < 100) {
      $('.hide-me').stop(true, true).animate({
        left: 0
      }, 1000);
    }
  }, 50);
});

If more than one animation method is called on the same element, the later animations are placed in the effects queue for the element. These animations will not begin until the first one completes. When .stop() is called, the next animation in the queue begins immediately. If the clearQueue parameter is provided with a value of true, then the rest of the animations in the queue are removed and never run.

Upvotes: 1

Related Questions