Home » Javascript » Chart.js 2.7.0 – Pie Chart – Determine width of pie slice to fillText (or not)

Chart.js 2.7.0 – Pie Chart – Determine width of pie slice to fillText (or not)

Posted by: admin November 1, 2017 Leave a comment

Questions:

I’ve figured out how to fillText into a Pie Chart slice, from code I found here:

https://jsfiddle.net/h1z7gtaw/6/

var data = {
    datasets: [{
        data: [218,1504,7,1,19],
         borderColor: ['blue','orange','red','green','purple'],
         borderWidth: 1,
         backgroundColor: [Color('blue').alpha(0.5).rgbString(),Color('orange').alpha(0.5).rgbString(),Color('red').alpha(0.5).rgbString(),Color('green').alpha(0.5).rgbString(),Color('purple').alpha(0.5).rgbString()],
        label: 'My dataset' // for legend
    }],
    labels: ['(empty)','TeamA','TeamB','TeamC','TeamD']
};

var pieOptions = {
   responsive: true,
   maintainAspectRatio: false,
   legend : { display: true, position: 'bottom' },
   title: { display: true, fontSize: 14,
            text: 'A Title'
  },
  hover: { animationDuration: 0 },
  animation: {
    duration: 500,
    easing: "easeOutQuart",
    onComplete: function () {
      var ctx = this.chart.ctx;
      ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
      ctx.textAlign = 'center';
      ctx.textBaseline = 'bottom';
      ctx.fillStyle = 'black';

      this.data.datasets.forEach(function (dataset) {

        for (var i = 0; i < dataset.data.length; i++) {
          var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
              total = dataset._meta[Object.keys(dataset._meta)[0]].total,
              mid_radius = model.innerRadius + (model.outerRadius - model.innerRadius)/2,
              start_angle = model.startAngle,
              end_angle = model.endAngle,
              mid_angle = start_angle + (end_angle - start_angle)/2;

          var x = mid_radius * Math.cos(mid_angle);
          var y = mid_radius * Math.sin(mid_angle);

console.log(dataset.data[i] + " --- " + start_angle + " --- " + end_angle);

          var percent = String(Math.round(dataset.data[i]/total*100)) + "%";
          ctx.fillText(dataset.data[i], model.x + x, model.y + y);
          // Display percent in another line, line break doesn't work for fillText
          ctx.fillText(percent, model.x + x, model.y + y + 15);
        }
      });               
    }
  }
};

var pieChartCanvas = $("#pieChart");
var pieChart = new Chart(pieChartCanvas, {
  type: 'pie', // or doughnut
  data: data,
  options: pieOptions
});

Which is great, when you have wonderfully proportional pie slices, where the text fits perfectly into them.

Well, I used data of [218, 1504, 7, 1, 19], and as you can imagine (or look at the jsfiddle!), the text displays nicely in the 218 and 1504 slices, but 7, 1, 19 are a bunch of overlapping garbled mess.

What do people do here, to handle that?

I’ve thought that if, based on the x/y coordinates of where I’m going to draw, I could calculate some type of width, I could then measure the text that I’m going to write, and if it’s not big enough, I could either rotate it some, or not draw it at all.

But figuring out that pie slice width is becoming difficult for me. In addition, I print out (through console.log) the start_angle and end_angle, and I get numbers like:

data --- start_angle --- end_angle
218 --- -1.5707963267948966 --- -0.7876434411658801
1504 --- -0.7876434411658801 --- 4.615392980788435
7 --- 4.615392980788435 --- 4.640540091794872
1 --- 4.640540091794872 --- 4.644132536224363
19 --- 4.644132536224363 --- 4.71238898038469

And maybe I missed this day in geometry class, but I don’t know what these angles are supposed to represent when I see -1.57, -0.7878, and numbers in the 4’s.

Any help would be appreciated and awesome. Thank you.

Answers: