Start animated number counter with JQuery when someone scrolls to ID

Viewed 1833

Does anyone know how to start the number counter animation when you scroll to a specific parent id like #counter-container?

$(window).scroll(startCounter);

function startCounter() {
  if ($(window).scrollTop() > 200) {
    $(window).off("scroll", startCounter);
    $('.count').each(function() {
      var $this = $(this);
      jQuery({
        Counter: 0
      }).animate({
        Counter: $this.text().replace(/,/g, '')
      }, {
        duration: 1000,
        easing: 'swing',
        step: function() {
          $this.text(commaSeparateNumber(Math.floor(this.Counter)));
        },
        complete: function() {
          $this.text(commaSeparateNumber(this.Counter));
          //alert('finished');
        }
      });
    });

    function commaSeparateNumber(val) {
      while (/(\d+)(\d{3})/.test(val.toString())) {
        val = val.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
      }
      return val;
    }
  }
}
#counter-container {
  margin-top: 1000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Scroll down...
<div id="counter-container">
  <span class="count">6,000</span>
  <span class="count">600</span>
  <span class="count">60</span>
</div>

1 Answers

To determine if scrolling has gone past a certain element you can compare the window scroll position + height, to the vertical offset of the target element. Try this:

$(window).scroll(startCounter);

function startCounter() {
  let scrollY = (window.pageYOffset || document.documentElement.scrollTop) + window.innerHeight;
  let divPos = document.querySelector('#counter-container').offsetTop;

  if (scrollY > divPos) {
    $(window).off("scroll", startCounter);

    $('.count').each(function() {
      var $this = $(this);
      jQuery({
        Counter: 0
      }).animate({
        Counter: $this.text().replace(/,/g, '')
      }, {
        duration: 1000,
        easing: 'swing',
        step: function() {
          $this.text(commaSeparateNumber(Math.floor(this.Counter)));
        },
        complete: function() {
          $this.text(commaSeparateNumber(this.Counter));
          //alert('finished');
        }
      });
    });

    function commaSeparateNumber(num) {
      return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    }
  }
}
#spacer {
  height: 1000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Scroll down...
<div id="spacer"></div>
<div id="counter-container">
  <span class="count">6,000</span>
  <span class="count">600</span>
  <span class="count">60</span>
</div>

Also note that I implemented a more robust version of your number grouping logic, taken from this answer.

Related