javascriptjqueryjquery-waypoints

Counter continues to count (incorrectly) when div is in view


I have a number counter and I'm using waypoints to run the counter when the #ticker div is in view.

The counter starts when the div is in view, so that's not the issue. But here is a use case of my current issue:

  1. Scroll down in the demo below until you get to the ticker text.
  2. Wait for the ticker to stop counting (when it's reached the static value of 16,000+.
  3. Now, scroll down and up the page again until the ticker is in view again, the ticker now is sometimes counting down and then stops at weird numbers, i.e. mine is currently stopped at 15,604+ when it should always end at 16,000+.

Unsure why this is happening?

demo:

$(document).ready(function() {
  $('#ticker').waypoint({
    handler: function() {
      $('.count').each(function() {
        const initial = $(this).text()
        const format = formatter(initial)
        $(this).prop('Counter', 0).animate({
          Counter: format.value
        }, {
          duration: 1500,
          easing: 'swing',
          step: function(now) {
            $(this).text(format.revert(Math.ceil(now)));
          }
        });
      });
    },
    offset: '100%'
  });
})


// keep string after count
function formatter(str) {
  const char = 'x'
  const template = str.replace(/\d/g, char)
  const value = str.replace(/\D/g, '')

  function revert(val) {
    const valStr = val.toString()
    let result = ''
    let index = 0
    for (let i = 0; i < template.length; i++) {
      const holder = template[i]
      if (holder === char) {
        result += valStr.slice(index, index + 1)
        index++
      } else {
        result += holder
      }
    }
    return result
  }
  return {
    template: template,
    value: value,
    revert: revert
  }
}
.gap{
  background: lightgrey;
  height: 600px;
}

.gap2{
  background: blue;
  height: 600px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/jquery.waypoints.min.js"></script>

<div class="gap"></div>
<div id="ticker">
  <span class="count counter">16,000+</span>
</div>
<div class="gap2"></div>


Solution

  • If you scroll down till ticker and wait for 16000 to complete and again scroll up and wait for 16000 to complete and then again come down it will work.

    The code is absolutely correct, except this line const initial = $(this).text(). You are using a span element text itself to get the maximum counter number.

    Whenever you scroll too fast then code will set whatever value present in the span element to the maximum counter. That's why you are getting wired behavior.

    Please rewrite your handler code like this

    $(document).ready(function () {
      var initialValue = $('#ticker .count').text()
      $('#ticker').waypoint({
        handler: function () {
          $('.count').each(function () {
            const format = formatter(initialValue)
    
            $(this).prop('Counter', 0).animate({
              Counter: format.value
            }, {
              duration: 1500,
              easing: 'swing',
              step: function (now) {
                $(this).text(format.revert(Math.ceil(now)));
              }
            });
          });
        },
        offset: '100%'
      });
    })