Search code examples
d3.jssvgc3.jsdonut-chart

C3 - How to center text in donut chart?


i have a problem with C3 donut chart - it doesn't center text inside chart: http://jsfiddle.net/aspirisen/q8h39/83/

c3.generate({
  legend: {
    show: false,
    position: 'right'
  },
  data: {
    columns: [
      ['data1', 50],
      ['data2', 50],
    ],
    type: 'donut',
    onclick: function (d, i) { console.log("onclick", d, i); },
    onmouseover: function (d, i) { console.log("onmouseover", d, i); },
    onmouseout: function (d, i) { console.log("onmouseout", d, i); }
  },
  tooltip: {
    show: false
  },
  donut: {
    width: 26,
    label: {
      format: function (value, ratio, id) {
        return (ratio * 100).toFixed(0).toString()
      }
    }
  }
});

enter image description here

Ho to fix this issue?

Thanks!


Solution

  • RANT WARNING -- This is why "helper" libraries built on top of d3 bother me so much. Creating this donut chart in straight d3 is about the same amount of code and you'd have absolute control over things like this.

    Regardless, you can fix this by re-computing the centroid after c3 has drawn and re-positioning the text (adjust the radius r to move the labels):

    // find all the labels
    d3.selectAll(".c3-chart-arc>text")
      .attr("transform", function(d,i){
        var r = 30, //<-- adjust this to move the labels
            a = (d.startAngle + d.endAngle) / 2 - (Math.PI / 2);
        // compute the new centroid
        return "translate(" + (Math.cos(a) * r) + "," + (Math.sin(a) * r) + ")";
    });
    

    Full code:

    c3.generate({
      legend: {
        show: false,
        position: 'right'
      },
      data: {
        columns: [
          ['data1', 32],
          ['data2', 50],
        ],
        type: 'donut',
        onclick: function (d, i) { console.log("onclick", d, i); },
        onmouseover: function (d, i) { console.log("onmouseover", d, i); },
        onmouseout: function (d, i) { console.log("onmouseout", d, i); }
      },
      tooltip: {
        show: false
      },
      donut: {
        width: 26,
        label: {
          format: function (value, ratio, id) {
            return (ratio * 100).toFixed(0).toString()
          }
        }
      }
    });
    
    setTimeout(function(){
    d3.selectAll(".c3-chart-arc>text")
    	.attr("transform", function(d,i){
      	var r = 30,
            a = (d.startAngle + d.endAngle) / 2 - (Math.PI / 2);
         console.log("translate(" + (Math.cos(a) * r) + "," + (Math.sin(a) * r) + ")")
        return "translate(" + (Math.cos(a) * r) + "," + (Math.sin(a) * r) + ")";
      });
    }, 100);
    #chart {
      width: 100px;
      height: 100px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.js"></script>
    <div id="chart"></div>