Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move labels' position on Chart.js pie

I'm using Chart.js and I'm trying to move the labels on my Pie chart outside of the pie area (see red X's):

enter image description here

This my code right now:

<div class="container" id="pieContainer">
    <h4 class="title">Title</h4>
    <center><canvas id="pie"></canvas></center>
</div>

<script>                                  
    var pieData = [
    {
        value: 39,
        color:"#335478",
        label: "Blue"
    },
    {
        value : 4,
        color : "#7f7f7f",
        label: "Grey"
    },
    {
        value : 57,
        color : "#99cb55",
        label: "Green"
    }
    ];

    var optionsPie = {
        responsive : true,
        tooltipEvents: [],
        showTooltips: true,
        onAnimationComplete: function() {
             this.showTooltip(this.segments, true);
        },
        tooltipTemplate: "<%= label %> - <%= value %>%"
    };
    new Chart(document.getElementById("pie").getContext("2d")).Pie(pieData, optionsPie);
</script>

I don't want to use legends and I couldn't find a built-in method to move labels. Is there a way to do that without changing chart.js? What's the best way to achieve my goal?

like image 367
DMEM Avatar asked Feb 08 '23 10:02

DMEM


2 Answers

Just extend the chart to do this. If your labels are static, it might be simpler to just change the tooltipPosition method instead.


Preview

enter image description here


Script

Chart.types.Pie.extend({
    name: "PieAlt",
    initialize: function(data){
        Chart.types.Pie.prototype.initialize.apply(this, arguments);

        var requiredSpace = 0;
        for (var i = 0; i < data.length; i++)
            requiredSpace = Math.max(ctx.measureText(Chart.helpers.template(this.options.tooltipTemplate, data[i])).width, requiredSpace);
        this.outerRadius -= (requiredSpace + 20);
    },
    draw: function(data){
        Chart.types.Pie.prototype.draw.apply(this, arguments);

        var self = this;
        ctx.save();
        ctx.font = Chart.helpers.fontString(self.options.scaleFontSize, self.options.scaleFontStyle, self.options.scaleFontFamily);
                ctx.textBaseline = "middle";
        self.segments.forEach(function (segment) {
            var outerEdge = Chart.Arc.prototype.tooltipPosition.apply({
                x: this.chart.width / 2,
                y: this.chart.height / 2,
                startAngle: segment.startAngle,
                endAngle: segment.endAngle,
                outerRadius: segment.outerRadius * 2 + 20,
                innerRadius: 0
            })

            var normalizedAngle = (segment.startAngle + segment.endAngle) / 2;
            while (normalizedAngle > 2 * Math.PI) {
                normalizedAngle -= (2 * Math.PI)
            }

            if (normalizedAngle < (Math.PI * 0.4) || (normalizedAngle > Math.PI * 1.5))
                ctx.textAlign = "start";
            else if (normalizedAngle > (Math.PI * 0.4) && (normalizedAngle < Math.PI * 0.6)) {
                outerEdge.y += 5;
                ctx.textAlign = "center";
            }
            else if (normalizedAngle > (Math.PI * 1.4) && (normalizedAngle < Math.PI * 1.6)) {
                outerEdge.y - 5;
                ctx.textAlign = "center";
            }
            else
                ctx.textAlign = "end";

            ctx.fillText(Chart.helpers.template(self.options.tooltipTemplate, segment), outerEdge.x, outerEdge.y);
        });

        ctx.restore();
    }
});

and then

new Chart(ctx).PieAlt(data, {
    showTooltips: false
});

Fiddle - http://jsfiddle.net/h8rggkhp/

like image 197
potatopeelings Avatar answered Feb 11 '23 00:02

potatopeelings


I recently ran into the same issue, and chartsjs-plugin-labels solved the issue for me.

Example:

import {Chart} from 'chartjs';
import 'chartjs-plugin-labels';

let options = {
  plugins: {
    labels: {
      position: 'outside',
      render: (args) => {
        return `${args.label}: ${args.value}%`;
      }
    }
  }
}

let data = {
  datasets: [
    {
      data: [39, 4, 57],
      labels: ['Blue', 'Gray', 'Green'],
    },
  ],
}

new Chart(ctx, {
  type: 'pie',
  data: data,
  options: options
}
like image 35
Luis Alvarez Avatar answered Feb 11 '23 01:02

Luis Alvarez