title: Modifying donut chart to "progress donut chart"
body: <p>I am trying to develop a d3 donut chart visual that simply takes a user defined percentage -- anywhere from 0 to 100%. From this value I want the donut to have segments equal to the proportion. For instance, if 50% then exactly half of the donut chart segments would be appended. Likewise, if 100% then the whole donut chart would be drawn; all the segments would be appended. I couldn't figure out how to achieve this in an elegant fashion, but I did find a crude workaround which you can see below in the snippet.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var data =
  [{'value':0,'interval':6.25},
  {'value':6.25,'interval':6.25},
  {'value':12.5,'interval':6.25},
  {'value':18.75,'interval':6.25},
  {'value':25,'interval':6.25},
  {'value':31.25,'interval':6.25},
  {'value':'none','interval':6.25},
  {'value':'none','interval':6.25},
  {'value':'none','interval':6.25},
  {'value':'none','interval':6.25},
  {'value':'none','interval':6.25},
  {'value':'none','interval':6.25},
  {'value':'none','interval':6.25},
  {'value':'none','interval':6.25},
  {'value':'none','interval':6.25},
  {'value':'none','interval':6.25}];
  
  
  var width = 960,
      height = 500,
      radius = Math.min(width, height) / 2;
  
  var color = d3.scale.linear()
          .range(["#0005fd","#00fe80"]).domain([0,35]);
  
  var explode = function(x,index) {
    var offset = (index==5) ? 80:0;
    var angle = (x.startAngle + x.endAngle)/2;
    var xOff = Math.sin(angle)*offset;
    var yOff = -Math.cos(angle)*offset;
    return "translate(" +xOff+","+yOff+ ")";
  }
  
  var arc = d3.svg.arc()
      .outerRadius(radius - 10)
      .innerRadius(radius - 70);
  
  var pie = d3.layout.pie()
      .padAngle(.05)
      .sort(null)
      .value(function(d) { return d.interval; });
  
  var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height)
    .append("g")
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
  
    var g = svg.selectAll(".arc")
        .data(pie(data))
      .enter().append("g")
        .attr("class", "arc");
  
    g.append("path")
        .attr("d", arc)
        //.attr('transform', explode)
        .style('stroke','none')
        .style("fill", function(d) {
          if (d.data.value=='none') {
            return 'none'
          }
          return color(d.data.value); });
  
    g.append("text")
        .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
        .attr("dy", ".35em")
        //.text(function(d) { return d.data.age; });
  
  svg.append('text')
      .text('37.5%') // magic number
      .attr('font-family','Play')
      .attr('font-size','140px')
      .attr('text-anchor','middle')
      .attr('x',0)
      .attr('y',40);
  
  
  function type(d) {
    d.interval = +d.interval;
    return d;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;!DOCTYPE html&gt;
  &lt;meta charset="utf-8"&gt;
  &lt;style&gt;
  
  &lt;/style&gt;
  &lt;body&gt;
  &lt;script src="http://d3js.org/d3.v3.min.js"&gt;&lt;/script&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>In essence, what is happening is the proportion of entries with values to the entries reading "none" is 37.5% -- which is my magic number (6 values and 10 nones, thus 6/16 = 37.5%). Needless to say this is not scalable at all.</p>
  
  <h2>Question</h2>
  
  <p>Is there any built-in means or other less labor-intensive solutions at my particular juncture? I just want to be able to pass a number from 0 to 100 to a function then have that percentage of the donut segments drawn out. In my particular case I chose 6.25 because it seemed to be the most aesthetically pleasing.</p>
  
  <p>Perhaps a custom fill with transparency to simulate the effect of having exploded segments? Seems too hacky...</p>
  
  <p><strong>Note:</strong> Versions are optional. That is to say I'm not opposed to d3.v5 solutions, I just used d3.v3 since I did not use donuts in v5 yet.</p>