0

I have 4 divs with heights set to window height. I want on each scroll down to scroll to the next one, however after the first scroll down it just keeps on scrolling, seemingly ignoring is:animated

<style>

    .div {
        width: 100%;
    }

    .red {
        background: red;
    }

    .yellow {
        background: yellow;
    }

    .green {
        background: green;
    }

    .blue {
        background: blue;
    }

</style>

<div id="id0" data-id="0" class="nbhd red scrolledto"></div>
<div id="id1" data-id="1" class="nbhd yellow"></div>
<div id="id2" data-id="2" class="nbhd green"></div>
<div id="id3" data-id="3" class="nbhd blue"></div>



function setHeights() {
        $('.nbhd').css('height', window.innerHeight);
    }

    function scrollSections() {

        if ($('body, html').is(':animated')) {
            return;
        }

        var currentSectionId = $('.nbhd.scrolledto').data('id');

        currentSectionId++;

        $('.scrolledto').removeClass('scrolledto');

        var section = $('#id'+currentSectionId);

        section.addClass('scrolledto');

        var pos = section.offset().top;

        $('body, html').animate({scrollTop: pos}, 1000, function() {
            console.log('animated');
        });

    }

    setHeights();



    $( window ).on( "scroll", function() {
        scrollSections();
    });

fiddle: https://jsfiddle.net/2d47k6af/

I also get animated logged 6 times for some reason, I expected 3.

dzimi
  • 769
  • 3
  • 10
  • 20
  • 2
    You have `animated` logged 6 times because it is logged 3 times for `body`, and 3 times for `html` – Pierre May 28 '16 at 10:09
  • Oh, thanks for that. – dzimi May 28 '16 at 10:10
  • You can use a global variable for resolve your problem : define `var isAnimated = false;` at the top of the script ; Set it to true when `$(window).on('scroll')` ; And reset it to false at the callback of `$('html, body').animate()` – Pierre May 28 '16 at 10:13
  • Doesn't work, if I do that it never even fires in the first place. – dzimi May 28 '16 at 10:17

2 Answers2

3

I guess this is what you're going for: https://jsfiddle.net/2d47k6af/5/

The problem was that you can't distinguish scroll events triggered by JavaScript and by user themself. So when you run the animation it fired many $(window).on("scroll", ...); events that were ignored thanks to $('body, html').is(':animated') that worked as expected.

However the last scroll event occured probably after the animation has ended so function scrollSections() was called one more time which triggered another animation and so on. My solution would be to add a short timeout after the animation has ended and before it's ready to another user triggered scroll:

$('body, html').animate({scrollTop: pos}, 1000, function() {
  console.log('animated');
  ignoreScrollEvents = true;

  setTimeout(function() {
    ignoreScrollEvents = false;
  }, 100);

});
Community
  • 1
  • 1
martin
  • 93,354
  • 25
  • 191
  • 226
0

You can to use variable to achieve, what you want:

function setHeights() {
  $('.nbhd').css('height', window.innerHeight);
}


var isAnimated = false; // Initialize variable
function scrollSections() {
  if (isAnimated) return; // Previous animation still in action
  isAnimated = true; // lock it
  var currentSectionId = $('.nbhd.scrolledto').data('id');

  currentSectionId++;
  var section = $('#id'+currentSectionId);
  if (!section.length) {
    currentSectionId = 0;
    section = $('#id0');
  }

  $('.scrolledto').removeClass('scrolledto');

  section.addClass('scrolledto');

  var pos = section.offset().top;

  $('body').animate({scrollTop: pos}, 1000, function() {
      setTimeout(function(){
        isAnimated = false; // unlock it on next eventloop tick
      })
  });
}

setHeights();



$( window ).on( "scroll", function() {
    scrollSections();
});
.div {width: 100%;}
.red {background: red;}
.yellow {background: yellow;}
.green {background: green;}
.blue {background: blue;}
<div id="id0" data-id="0" class="nbhd red scrolledto"></div>
<div id="id1" data-id="1" class="nbhd yellow"></div>
<div id="id2" data-id="2" class="nbhd green"></div>
<div id="id3" data-id="3" class="nbhd blue"></div>

<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
vp_arth
  • 14,461
  • 4
  • 37
  • 66