Search code examples
javascripthtml5-canvas

Make Html5 Canvas progress bar to circle from semi circle


I am creating one progress bar using Html5 Canvas, Where i need to show the progress bar based on provided value. Now user set some value and based on it the progress bar should complete the progress.

I have found some code from google and tried to implement the same, But since I don't have much idea about the Html5 Canvas. Need some of your help to complete the same.

The current code is showing the progress as semi circle till 45 degree only.

below are the screenshot FYR.

enter image description here

var
  canv = document.getElementById('canv'),
  ctx = canv.getContext('2d');

canv.width = 400;
canv.height = 400;

var
  center_x = canv.width / 2,
  center_y = canv.height + 50,
  radius = 150;

ctx.lineWidth = 15;
ctx.strokeStyle = '#492528';

ctx.beginPath();
ctx.arc(center_x, center_y, radius, 0, Math.PI, true);
//ctx.arc(100, 75, 50, 0, Math.PI + 0.2, true);
ctx.stroke();

var
  l_ = -2.93,
  l_t = -2.3,
  simpleAnimationTimer = setInterval(function() {
    ctx.fillStyle = '#301618';
    ctx.beginPath();
    ctx.arc(center_x, center_y, radius, l_, Math.PI, true);
    ctx.lineTo(center_x - 10, center_y);
    //ctx.lineTo(center_x, center_y - 20);
    ctx.fill();

    var
      grad = ctx.createRadialGradient(center_x, center_y, 50, center_x, center_y, radius);

    // grad.addColorStop(0.2, 'rgba(246,178,86, 0.2)');
    // grad.addColorStop(0.3, 'rgba(246,178,86, 0.1)');
    // grad.addColorStop(.5, 'rgba(45, 14, 16, 0.5)');
    grad.addColorStop(1, '#53301A');
    grad.addColorStop(0, 'rgba(90, 14, 16, 1)');

    ctx.fillStyle = grad;
    ctx.beginPath();
    ctx.arc(center_x, center_y, radius, l_, Math.PI + 0.2, true);
    ctx.lineTo(center_x - 20, center_y);
    ctx.lineTo(center_x, center_y - 40);
    ctx.fill();

    ctx.lineWidth = 15;
    ctx.strokeStyle = '#F7B349';

    ctx.beginPath();
    ctx.arc(center_x, center_y, radius, l_, Math.PI + 0.2, true);
    ctx.stroke();

    l_ += .01;
    if (l_ > -2.30) {
      clearInterval(simpleAnimationTimer);
    }
  }, 20);

function drawTick(angle, from, to) {
  var
    angle = angle, // 168 is start
    xs = center_x + radius * Math.cos(-angle * Math.PI) * from,
    ys = center_y + radius * Math.sin(-angle * Math.PI) * from,
    xe = center_x + radius * Math.cos(-angle * Math.PI) * to,
    ye = center_y + radius * Math.sin(-angle * Math.PI) * to;

  ctx.lineWidth = 1;
  ctx.strokeStyle = '#8A6047';

  ctx.beginPath();
  ctx.moveTo(xs, ys);
  ctx.lineTo(xe, ye);
  ctx.stroke();
}

// first level outer ticks
for (i = 0; i < 157; i++) {
  drawTick(168 - i * 1, 1.1, 1.06);
}

// dots
for (i = 0; i < 157; i++) {
  drawTick(168 - i * 1, 1.25, 1.255);
}

ctx.lineWidth = 1;
ctx.strokeStyle = '#603738';

ctx.beginPath();
ctx.arc(center_x, center_y, radius + 55, -0.2, Math.PI + 0.2, true);
ctx.stroke();

// first level outer ticks
for (i = 0; i < 58; i++) {
  drawTick(167 - i * 2.7, 1.3, 1.35);
}
body {
  margin: 0;
}
<canvas id="canv">Your browser not support canvas.</canvas>


Solution

  • We should consider the progress percentage and compute the angle to generate the arc when we increase progress.

    // Draw progress circle
    var endAngle = (progress / maxProgress) * 2 * Math.PI - Math.PI / 2;
    ctx.beginPath();
    ctx.arc(center_x, center_y, radius, -Math.PI / 2, endAngle, false);
    ctx.strokeStyle = '#4caf50';
    ctx.stroke();
    ctx.closePath();
    

    var canv = document.getElementById('canv'),
            ctx = canv.getContext('2d');
    
        canv.width = 400;
        canv.height = 400;
    
        var center_x = canv.width / 2,
            center_y = canv.height / 2,
            radius = 150;
    
        ctx.lineWidth = 15;
        ctx.strokeStyle = '#492528';
    
        ctx.beginPath();
        ctx.arc(center_x, center_y, radius, 0, 2 * Math.PI, true);
        ctx.stroke();
    
        var progress = 0;
        var maxProgress = 100; // maximum progress value
        var animationSpeed = 2; // speed of the animation
    
        var simpleAnimationTimer = setInterval(function() {
          ctx.clearRect(0, 0, canv.width, canv.height);
    
          // Draw background circle
          ctx.beginPath();
          ctx.arc(center_x, center_y, radius, 0, 2 * Math.PI, true);
          ctx.strokeStyle = '#e6e6e6';
          ctx.stroke();
          ctx.closePath();
    
          // Draw progress circle
          var endAngle = (progress / maxProgress) * 2 * Math.PI - Math.PI / 2;
          ctx.beginPath();
          ctx.arc(center_x, center_y, radius, -Math.PI / 2, endAngle, false);
          ctx.strokeStyle = '#4caf50';
          ctx.stroke();
          ctx.closePath();
    
          // Draw progress text
          ctx.font = '20px Arial';
          ctx.fillStyle = '#000';
          ctx.textAlign = 'center';
          ctx.textBaseline = 'middle';
          ctx.fillText(Math.round((progress / maxProgress) * 100) + '%', center_x, center_y);
    
          progress += animationSpeed;
          if (progress > maxProgress) {
            clearInterval(simpleAnimationTimer);
          }
        }, 50);
    <!DOCTYPE html>
    <html>
    <head>
      <title>Full Circle Progress Bar</title>
      <style>
        canvas {
          display: block;
          margin: 0 auto;
          background-color: #f0f0f0;
        }
      </style>
    </head>
    <body>
      <canvas id="canv"></canvas>
    </body>
    </html>

    check Fiddle: jsfiddle.net/0m2qfoeu.