Skip to content
Advertisement

Increment over time all elements of a class

In my homepage, I’m trying to have a bunch of numbers go from 0 to their default value. Those numbers are all inside spans with a specific class. And, I have some jquery to animate them.

$(".number_up").each(function(){
        num_to_up = parseInt($(this).text().replace(" ",""));
        rythm = 3;
        start = 0;
        $(this).text(start);
        element = $(this);

        setInterval(function(){
          if(start < num_to_up)
          {
            start = start+rythm;
            $(element).text(start);
          }
        },0.001);

        $(element).text(num_to_up);

      });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="number_up">4 000</span>
<span class="number_up">4 000</span>
<span class="number_up">4 000</span>
<span class="number_up">4 000</span>
<span class="number_up">4 000</span>

But it only works for the last number in the list… all the previous ones stay at their default value. Any idea what I’m doing wrong ?

Advertisement

Answer

The issue is because you are not explicitly declaring your variables in the loop, so they are global. This means that all iterations of each() are interfering with the values. The easy way to solve this is to declare the variables in scope by using the let keyword.

Also, an interval is set in milliseconds, so 0.001 is 0.000001 seconds – far quicker than JS can manage. I’d suggest changing this to something more manageable, eg. 25ms, and using a bigger delta between updates to maintain the speed of the count.

In addition, you need to remove the intervals when the final value is hit. Otherwise they will be running infinitely and may affect the performance of the page. To destroy the intervals call clearInterval() when the target value has been met.

Finally, I would suggest you make the rhythm value something which is a multiple of num_to_up. Otherwise you’ll not hit your exact value – this is why you see 4002 at the end, because 3 is not a divisor of 4000.

Here’s an updated working example:

$(".number_up").each(function() {
  let $element = $(this);
  let start = 0;
  let delta = 25;
  let limit = parseInt($element.text().replace(" ", ""), 10);
  $element.text(start);

  let interval = setInterval(function() {
    if (start < limit) {
      $element.text(start += delta);
    } else {
      clearInterval(interval);
    }
  }, 25);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="number_up">4 000</span>
<span class="number_up">4 000</span>
<span class="number_up">4 000</span>
<span class="number_up">4 000</span>
<span class="number_up">4 000</span>

Note that I used the $element variable you stored to reference the DOM in order to increase performance in the loop.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement