Simple Canvas Progress Pie Graph

by sjmcpherson

HTML

<div class="progress">
  <ul><li>Completed</li></ul>
  <canvas id="bar" width="200" height="200"></canvas>
</div>

CSS

*,*:before,*:after{box-sizing:border-box;margin:0;padding:0;}
body{font-family:arial;}
ul{list-style:none;width:100%;}
li{margin-left:35%;position:absolute;top:88px;}
li:before{content:"";top:5px;left:-15px;position:absolute;width:10px;height:10px;border-radius:50%;background-color:#f00;display:block;}
.progress {
  margin:0 auto;
  position: relative;
  width: 200px;
  height: 200px;
  text-align:center;
}
.progress:before {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  border: 30px solid #444;
  border-radius: 50%;
}
#bar {
  position: absolute;
  top: 0;
  left: 0;
}

JavaScript

// CANVAS
var canvas = document.getElementById('bar'),
    width = canvas.width,
    height = canvas.height;

// CANVAS PROPERTIES
var ctx = canvas.getContext('2d');
ctx.lineWidth = 30;
ctx.strokeStyle = '#f00';
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = 0;
ctx.shadowColor = '#f00';

// CANVAS MATHS
var x = width / 2,
    y = height / 2,
    radius = 85,
    circum = Math.PI * 2,
    start = Math.PI / -2, // Start position (top)
    finish = 67, // Finish (in %)
    curr = 0; // Current position (in %)

// CANVAS ANIMATION

// Enables browser-decided smooth animation (60fps)
var raf =
    window.requestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.msRequestAnimationFrame;
window.requestAnimationFrame = raf;

// Animate function
function animate(draw_to) {
  // Clear off the canvas
  ctx.clearRect(0, 0, width, height);
  // Start over
  ctx.beginPath();
  // arc(x, y, radius, startAngle, endAngle, anticlockwise)
  // Re-draw from the very beginning each time so there isn't tiny line spaces between each section (the browser paint rendering will probably be smoother too)
  ctx.arc(x, y, radius, start, draw_to, false);
  // Draw
  ctx.stroke();
  // Increment percent
  curr++;
  // Animate until end
  if (curr < finish + 1) {
    // Recursive repeat this function until the end it reached
    requestAnimationFrame(function () {
      animate(circum * curr / 100 + start);
    });
  }
}

animate();