javascripthtmlcssprogress-bar

progress bar complete progress based on provided max value


I have created one progress bar using HTML, CSS and Javascript. It is working fine till 100 value provided. If i provide more than 100 then it complete the progress but still the value is keep changing, Until it not reached the max value.

Expectation: Based on provided value only it should complete the progress.

Code used is below:

window.addEventListener("load", function
(event){
  let circle = document.querySelectorAll('.circle');
  console.log(circle);
  circle.forEach(function(progress){
    let degree = 0;
    let percentage=0;
    var targetDegree = parseInt(progress.getAttribute('data-degree'));
      let color = progress.getAttribute('data-color');
      let number = progress.querySelectorAll('.number');
      let childNumber = progress.querySelectorAll('.totalfilling');
      var interval = setInterval(function(){
        degree+=1;
        if(degree > targetDegree){
          clearInterval(interval);
          return;
        }
        if(targetDegree > 100){
            percentage = targetDegree / degree;
            console.log(percentage);
        }
        progress.style.background = `conic-gradient(
        ${color} ${degree}%, #222 0%)`;
        number[0].innerHTML = degree;
        console.log(degree);
        number[0].style.color =  color;
        childNumber[0].innerHTML = '<h5>'+targetDegree+'</h5>'
      }, 50)
  });
});
*
{
  margin:0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body{
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}
.container{
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 40px;
}
.container .circle{
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  width: 200px;
  height: 200px;
  border-radius: 50%;
}
.container .circle::before{
  content: '';
  position:absolute;
  inset: 5px;
  border-radius: 50%;
  background: #222;
  opacity: 0.8;
}
.container .circle::after{
  content: '';
  position:absolute;
  width:120px;
  height: 120px;
  border-radius: 50%;
  background: #fff;
  border: 15px solid #4d4c51;
  box-shadow: inset 0 5px 10px rgba(0,0,0,0.25),
  0 10px 10px rgba(0,0,0,0.75),
  0 -2px 2px rgba(255,255,255,0.5),
  inset 0 4px 2px rgba(0,0,0,0.25),
  inset 0 -2px 2px rgba(255,255,255,0.5);
}
.container .circle .number{
  position:relative;
  color: #fff;
  z-index: 10;
  line-height: 1em;
  font-size: 2em;
}
.container .circle .number span{
  font-size: 0.5em;
  font-weight: 500;
}
.container .circle h4{
  position:relative;
  color: #0b60e9;
  z-index: 10;
  font-weight: 500;
  font-size: 0.8em;
  line-height: 0.6em;
}
.countperhour{
    margin-left:40px;
    font-size:18px;
}
.totalfilling{
    margin-top:10px;
    color: black;
  z-index: 10;
  font-weight: 500;
  font-size: 18px;
  line-height: 0.6em;
}
 <div class="App">
      <div class="container">
        <div class="circle" data-degree="200" data-color="#0b60e9">
        <div class="countperhour">
         <h4>C/h</h4>
         </div>
          <h2 class="number"></h2>
          <div class="totalfilling">
            <h5>1000</h5>
          </div>
        </div>
      </div>

Kindly check the above code and suggest.


Solution

  • You need to correct your percentage and correct your condition for stopping your interval and count. You also don't need to use querySelectorAll

    window.addEventListener("load", function
    (event){
      let circle = document.querySelectorAll('.circle');
      console.log(circle);
      circle.forEach(function(progress){
        let degree = 0;
        let percentage=0;
        var targetDegree = parseInt(progress.getAttribute('data-degree'));
          let color = progress.getAttribute('data-color');
          let number = progress.querySelector('.number');
          let childNumber = progress.querySelector('.totalfilling');
          var interval = setInterval(function(){
            degree+=1;
            if(percentage >= 1){
              clearInterval(interval);
              return;
            }
            percentage = degree/targetDegree ;
            progress.style.background = `conic-gradient(
            ${color} ${percentage*100}%, #222 0%)`;
            number.innerHTML = degree;
            console.log(degree);
            number.style.color =  color;
            childNumber.innerHTML = '<h5>'+targetDegree+'</h5>'
          }, 50)
      });
    });
    *
    {
      margin:0;
      padding: 0;
      box-sizing: border-box;
      font-family: 'Poppins', sans-serif;
    }
    body{
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
    }
    .container{
      position: relative;
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 40px;
    }
    .container .circle{
      position: relative;
      display: flex;
      justify-content: center;
      align-items: center;
      flex-direction: column;
      width: 200px;
      height: 200px;
      border-radius: 50%;
    }
    .container .circle::before{
      content: '';
      position:absolute;
      inset: 5px;
      border-radius: 50%;
      background: #222;
      opacity: 0.8;
    }
    .container .circle::after{
      content: '';
      position:absolute;
      width:120px;
      height: 120px;
      border-radius: 50%;
      background: #fff;
      border: 15px solid #4d4c51;
      box-shadow: inset 0 5px 10px rgba(0,0,0,0.25),
      0 10px 10px rgba(0,0,0,0.75),
      0 -2px 2px rgba(255,255,255,0.5),
      inset 0 4px 2px rgba(0,0,0,0.25),
      inset 0 -2px 2px rgba(255,255,255,0.5);
    }
    .container .circle .number{
      position:relative;
      color: #fff;
      z-index: 10;
      line-height: 1em;
      font-size: 2em;
    }
    .container .circle .number span{
      font-size: 0.5em;
      font-weight: 500;
    }
    .container .circle h4{
      position:relative;
      color: #0b60e9;
      z-index: 10;
      font-weight: 500;
      font-size: 0.8em;
      line-height: 0.6em;
    }
    .countperhour{
        margin-left:40px;
        font-size:18px;
    }
    .totalfilling{
        margin-top:10px;
        color: black;
      z-index: 10;
      font-weight: 500;
      font-size: 18px;
      line-height: 0.6em;
    }
        <div class="App">
            <div class="container">
                <div class="circle" data-degree="200" data-color="#0b60e9">
                    <div class="countperhour">
                        <h4>C/h</h4>
                    </div>
                    <h2 class="number"></h2>
                    <div class="totalfilling">
                        <h5>1000</h5>
                    </div>
                </div>
            </div>
        </div>

    as you have only one element.