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 >4 000</span>
<span >4 000</span>
<span >4 000</span>
<span >4 000</span>
<span >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 ?
CodePudding user response:
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 >4 000</span>
<span >4 000</span>
<span >4 000</span>
<span >4 000</span>
<span >4 000</span>
Note that I used the $element
variable you stored to reference the DOM in order to increase performance in the loop.