I’m making an animated progress bar with setInterval that will call the function animate to increase the width of the .bar. I need to stop the setInterval when the counter is 100/the width of the bar is 100% and restart it again for the next bar.
The problem is that the for loop seems immediately called the function three times (because the length of the bar is 3) instead of waiting for the current bar to be finished and then only resetting the counter to 0 and restarting the setInterval for the next bar…
I’ve been struggling with this for about an hour, please help.
const items = document.getElementsByClassName('bar');
for (let i = 0; i < items.length; i++) {
let intervalId,
counter = 0;
function animate() {
if(counter >= 100) {
clearInterval(intervalId);
counter = 0;
} else {
counter++;
items[i].style.width = `${counter}%`;
}
}
intervalId = setInterval(animate, 10);
}
#main {
display: flex;
gap: 30px;
}
.item {
background-color: gray;
width: 100%;
height: 3px;
}
.bar {
background-color: orange;
width: 0;
height: 100%;
}
<div id="main">
<div class="item">
<div class="bar"></div>
</div>
<div class="item">
<div class="bar"></div>
</div>
<div class="item">
<div class="bar"></div>
</div>
</div>
>Solution :
Put the code for a single progress bar in a function, which takes the item index as an argument. Then when you reach the end of one progress bar, you can stop it and call the function for the next one.
const items = document.getElementsByClassName('bar');
function progressBar(i) {
if (i < items.length) {
let intervalId,
counter = 0;
function animate() {
if (counter >= 100) {
clearInterval(intervalId);
progressBar(i + 1);
} else {
counter++;
items[i].style.width = `${counter}%`;
}
}
intervalId = setInterval(animate, 10);
}
}
progressBar(0);
#main {
display: flex;
gap: 30px;
}
.item {
background-color: gray;
width: 100%;
height: 3px;
}
.bar {
background-color: orange;
width: 0;
height: 100%;
}
<div id="main">
<div class="item">
<div class="bar"></div>
</div>
<div class="item">
<div class="bar"></div>
</div>
<div class="item">
<div class="bar"></div>
</div>
</div>