skip to Main Content

I am creating one SVG Circular Progress bar. It is working, But when i pass some value, Hence based on that value it is not completing the progress.

Below is the code, Which i tried so far

    window.addEventListener("load", function
(event){
  let progressbar = document.querySelectorAll('.progress-bar');
  progressbar.forEach(function(circle){
    let degree = 0;
    let percentage=0;
    var targetDegree = parseInt(circle.getAttribute('data-degree'));
      var element = circle.children;
       var childElem = element.item(1);
      let color = circle.getAttribute('data-color'); 
       let number = document.querySelector('.text');
       let childNumber = document.querySelector('.totalfilling'); 
       var interval = setInterval(function(){ 
         degree+=1;
         if(percentage >= 1){ 
         clearInterval(interval);
           return; 
         } 
         percentage = degree/targetDegree ;
         var progressCalc = 848 - (848 * targetDegree) / 100;
     
      //childElem.style = `stroke-dashoffset: calc(${progressCalc})`;
        childElem.style.background = `conic-gradient( 
         ${color} ${percentage*100}%, #222 0%)`;
         number.innerHTML = degree;
         number.style.color =  color;
        childNumber.innerHTML = '<h5>'+targetDegree+'</h5>'
      },50)
  });
});
body {
        width: 100%;
        height: 100vh;
        margin: 0;
        padding: 0;
      }
      .center {
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        background: rgb(25, 25, 50);
      }
      .progress {
        width: 400px;
        height: 400px;
        background: rgb(255, 255, 255);
        border-radius: 5mm;
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
      }
      circle {
        fill: none;
      }
      svg {
        transform: rotate(90deg);
      }
      circle:nth-child(1) {
        stroke: rgb(240, 248, 255);
        stroke-width: 12px;
      }
      circle:nth-child(2) {
        stroke: rgb(78, 91, 205);
        stroke-dasharray: 848;
        stroke-linecap: round;
        stroke-width: 16px;
        animation: progress 1s ease;
      }
      @keyframes progress {
        from {
          stroke-dashoffset: 848;
        }
      }
      .text {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-family: poppins;
        font-size: 60px;
        color: rgb(78, 91, 205);
        font-weight: 500;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-direction: column;
      }
      .text span {
        font-size: 14px;
        color: rgb(78, 91, 205);
      }
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Circular Progress Bar</title>
  </head>
  <body>
    <div class="center">
      <div class="progress">
        <svg class="progress-bar" data-degree="75" data-color="#0b60e9" width="300" height="300">
          <circle class="progress-circle" cx="150" cy="150" r="135"></circle>
          <circle class="progress-circle" cx="150" cy="150" r="135"></circle>
           <div class="text">
          75
          <span>Completed</span>
        </div>
        <div class="totalfilling">
                    <h5>1000</h5>
                </div>
        </svg>
       
      </div>
    </div>
  </body>
</html>

In the above code i tried to use some max value, So the progress bar should complete based on the max value.
But this logic is not working.

Need help.

2

Answers


  1. So, basically if I good understanding your task, stroke doesn’t fill circle to value, right?

    If so, try change way how you calculate percentage.

    percentage = degree / 100;
    

    And then in relation to that adjust stroke-dashoffset

    Thing is that interval has to stop when the degree reaches the targetDegree

    if (degree >= targetDegree) {
      clearInterval(interval);
      return;
    }
    
        window.addEventListener("load", function (event) {
        let progressbar = document.querySelectorAll('.progress-bar');
        progressbar.forEach(function (circle) {
          let degree = 0;
          let percentage = 0;
          const targetDegree = parseInt(circle.getAttribute('data-degree'));
          const maxDegrees = 100;
          const circumference = 848;
          const element = circle.children;
          const childElem = element.item(1);
          const color = circle.getAttribute('data-color');
          const number = document.querySelector('.text');
          const childNumber = document.querySelector('.totalfilling');
    
          var interval = setInterval(function () {
            if (degree >= targetDegree) {
              clearInterval(interval);
              return;
            }
            degree += 1;
            percentage = degree / maxDegrees;
            const progressCalc = circumference - (circumference * percentage);
            childElem.style.strokeDashoffset = progressCalc;
            childElem.style.stroke = color;
            number.innerHTML = degree;
            number.style.color = color;
            childNumber.innerHTML = '<h5>' + targetDegree + '</h5>';
          }, 50);
        });
      });
    body {
        width: 100%;
        height: 100vh;
        margin: 0;
        padding: 0;
      }
      .center {
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        background: rgb(25, 25, 50);
      }
      .progress {
        width: 400px;
        height: 400px;
        background: rgb(255, 255, 255);
        border-radius: 5mm;
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
      }
      circle {
        fill: none;
      }
      svg {
        transform: rotate(-90deg);
      }
      circle:nth-child(1) {
        stroke: rgb(240, 248, 255);
        stroke-width: 12px;
      }
      circle:nth-child(2) {
        stroke: rgb(78, 91, 205);
        stroke-dasharray: 848;
        stroke-linecap: round;
        stroke-width: 16px;
      }
      .text {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-family: poppins;
        font-size: 60px;
        color: rgb(78, 91, 205);
        font-weight: 500;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-direction: column;
      }
      .text span {
        font-size: 14px;
        color: rgb(78, 91, 205);
      }
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Circular Progress Bar</title>
      </head>
      <body>
        <div class="center">
      <div class="progress">
        <svg class="progress-bar" data-degree="59" data-color="#0b60e9" width="300" height="300">
          <circle class="progress-circle" cx="150" cy="150" r="135"></circle>
          <circle class="progress-circle" cx="150" cy="150" r="135"></circle>
        </svg>
        <div class="text">
          75
          <span>Completed</span>
        </div>
        <div class="totalfilling">
          <h5>1000</h5>
        </div>
      </div>
    </div>
      </body>
    </html>
    Login or Signup to reply.
  2. If you use the pathLength attribute on the circle it is easier to calculate the stroke-dasharray and offset.

    Don’t use HTML inside the SVG element. In this case you can use the <text> element.

    let progressbar = document.querySelectorAll('.progress-bar');
    progressbar.forEach(function(circle) {
      let degree = 0;
      let percentage = 0;
      let targetDegree = parseInt(circle.dataset.degree);
      let childElem = circle.querySelector('circle:nth-child(2)');
      let number = circle.querySelector('.text');
      let childNumber = circle.querySelector('.totalfilling');
      childNumber.innerHTML = targetDegree;
      number.style.color = circle.dataset.color;
      var interval = setInterval(function() {
        degree += 1;
        if (degree >= targetDegree) {
          clearInterval(interval);
        }
        childElem.style.strokeDashoffset = degree - 100;
        number.innerHTML = degree;
      }, 50)
    });
    body {
      width: 100%;
      height: 100vh;
      margin: 0;
      padding: 0;
    }
    
    .center {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      background: rgb(25, 25, 50);
    }
    
    .progress {
      width: 400px;
      height: 400px;
      background: rgb(255, 255, 255);
      border-radius: 5mm;
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
    }
    
    circle {
      fill: none;
    }
    
    circle:nth-child(1) {
      stroke: rgb(240, 248, 255);
      stroke-width: 12px;
    }
    
    circle:nth-child(2) {
      stroke: rgb(78, 91, 205);
      stroke-dasharray: 848;
      stroke-linecap: round;
      stroke-width: 16px;
    }
    
    .text {
      font-family: poppins;
      font-size: 60px;
      font-weight: 500;
      fill: rgb(78, 91, 205);
      font-weight: 500;
    }
    <div class="center">
      <div class="progress">
        <svg class="progress-bar" data-degree="75"
          data-color="#0b60e9" width="320" height="300">
          <g transform="translate(150 150)">
            <circle class="progress-circle" r="135"></circle>
            <circle class="progress-circle" transform="rotate(90)"
              r="135" pathLength="100" stroke-dasharray="100 100"></circle>
            <text class="text" dominant-baseline="middle"
              text-anchor="middle"></text>
          </g>
          <text class="totalfilling" font-size="20" x="320" y="150"
          dominant-baseline="middle" text-anchor="end">test</text>
        </svg>
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search