Search code examples
javascripthtmlcsscanvasprogress-bar

Progress bar view without rotating around does not work


The following code is generating a circle bar by using canvas. Everything works fine. But when I tried to change the code so that the percent circle and value view dont rotate/circulate around until they reach the real position/value I run into problems. The graph should only view the percentage position within the circle and the value in the mittle of the circle without rotating/couting up to the real end value. I know I have to change/delete some things in the JS arcMove() function like deegres += 1 which is responsible for the rotation steps and so on, but if I tried it didnt work like it should.

window.onload = function() {
  var can = document.getElementById('canvas'),
      spanProcent = document.getElementById('procent'),
       c = can.getContext('2d');
 
  var posX = can.width / 2,
      posY = can.height / 2,
      fps = 1000 / 200,
      procent = 0,
      oneProcent = 360 / 100,
      result = oneProcent * 64;
  
  c.lineCap = 'round';
  arcMove();
  
  function arcMove(){
    var deegres = 0;
    var acrInterval = setInterval (function() {
      deegres += 1;
      c.clearRect( 0, 0, can.width, can.height );
      procent = deegres / oneProcent;

      spanProcent.innerHTML = procent.toFixed();

      c.beginPath();
      c.arc( posX, posY, 70, (Math.PI/180) * 270, (Math.PI/180) * (270 + 360) );
      c.strokeStyle = '#b1b1b1';
      c.lineWidth = '10';
      c.stroke();

      c.beginPath();
      c.strokeStyle = '#3949AB';
      c.lineWidth = '10';
      c.arc( posX, posY, 70, (Math.PI/180) * 270, (Math.PI/180) * (270 + deegres) );
      c.stroke();
      if( deegres >= result ) clearInterval(acrInterval);
    }, fps);
    
  }
  
  
}
:root {
  background: #fff;
}

span#procent {
  display: block;
  position: absolute;
  left: 50%;
  top: 50%;
  font-size: 50px;
  transform: translate(-50%, -50%);
  color: #3949AB;
}

span#procent::after {
  content: '%';
}

.canvas-wrap {
  position: relative;
  width: 300px;
  height: 300px;
}
<div class="canvas-wrap">
  <canvas id="canvas" width="300" height="300"></canvas>
  <span id="procent"></span>
</div>


Solution

  • In the arcMove function you have to set degree to result so the interval is done on first call. But if you do not want an animation than you should use a pure css way of displaying it. Checkout the following answer: https://stackoverflow.com/a/41147560/8820118

    window.onload = function() {
      var can = document.getElementById('canvas'),
          spanProcent = document.getElementById('procent'),
           c = can.getContext('2d');
     
      var posX = can.width / 2,
          posY = can.height / 2,
          fps = 1000 / 200,
          procent = 0,
          oneProcent = 360 / 100,
          result = oneProcent * 64;
      
      c.lineCap = 'round';
      arcMove();
      
      function arcMove(){
        var deegres = result; // change degrees to result, than you won't have the animation.
        var acrInterval = setInterval (function() {
          deegres += 1;
          c.clearRect( 0, 0, can.width, can.height );
          procent = deegres / oneProcent;
    
          spanProcent.innerHTML = procent.toFixed();
    
          c.beginPath();
          c.arc( posX, posY, 70, (Math.PI/180) * 270, (Math.PI/180) * (270 + 360) );
          c.strokeStyle = '#b1b1b1';
          c.lineWidth = '10';
          c.stroke();
    
          c.beginPath();
          c.strokeStyle = '#3949AB';
          c.lineWidth = '10';
          c.arc( posX, posY, 70, (Math.PI/180) * 270, (Math.PI/180) * (270 + deegres) );
          c.stroke();
          if( deegres >= result ) clearInterval(acrInterval);
        }, fps);
        
      }
      
      
    }
    :root {
      background: #fff;
    }
    
    span#procent {
      display: block;
      position: absolute;
      left: 50%;
      top: 50%;
      font-size: 50px;
      transform: translate(-50%, -50%);
      color: #3949AB;
    }
    
    span#procent::after {
      content: '%';
    }
    
    .canvas-wrap {
      position: relative;
      width: 300px;
      height: 300px;
    }
    <div class="canvas-wrap">
      <canvas id="canvas" width="300" height="300"></canvas>
      <span id="procent"></span>
    </div>