Gags
Gags

Reputation: 3829

set Pie chart labels exact in center of Slices of PIE highcharts

i am using highcharts in one of my project. Highcharts JQuery version is being used and below is the reference:

http://code.highcharts.com/highcharts.js

Code used to draw chart is as below:

$(function () {
    var chart = new Highcharts.Chart({
        chart: {
            renderTo: 'container',
            type:'pie'
        },
        xAxis: {
            categories: ['Jan', 'Feb', 'Mar', 'Apr']
        },

        plotOptions: {
            series: {
                dataLabels: {
                    enabled: true,
                    formatter: function() {
                        return Math.floor(this.percentage*100)/100 + ' %';
                    },
                    distance: 20,
                    connectorWidth : 0,
                    color: 'rgb(0, 127, 209)'
                }
            }
        },

        series: [{
            data: [29.9, 71.5, 106.4, 129.2,29.9, 71.5, 106.4, 
                  129.2,29.9, 71.5, 106.4, 129.2]        
        }]
    });
});

The problem here i am facing that Slice labels are running here and there. I want all labels exact in center of each slice.

JS Fiddle link for demo is PIE Chart JSFiddle

Upvotes: 2

Views: 2532

Answers (2)

Kacper Madej
Kacper Madej

Reputation: 7886

Simplest, but not precise way would be to set negative distance for dataLabels. Value of distance would be related to size of chart, so it is possible to update series (with new distance for dataLabels) in load (to initiatie correct position) and redraw (after change of chart's size) events.

Precise solution for placing each of dataLabels in center of its slice can be based on getting center of slice and placing labels there. To keep chart responsive this adjustment of labels positions should be performed after each change of chart's size - in load and redraw events of chart.

Example: http://jsfiddle.net/mo8dfztx/2/

function redrawDatalabels() {
    var chart = this,
        cX = chart.series[0].center[0],
        cY = chart.series[0].center[1],
        shapeArgs, ang, posX, posY, bBox;

    Highcharts.each(chart.series[0].data, function (point, i) {
        if (point.dataLabel) {
            bBox = point.dataLabel.getBBox();
            shapeArgs = point.shapeArgs;
            ang = (shapeArgs.end - shapeArgs.start) / 2 + shapeArgs.start;
            posX = cX + (shapeArgs.r / 2) * Math.cos(ang);
            posY = cY + (shapeArgs.r / 2) * Math.sin(ang);

            point.dataLabel._pos.x = posX + ((point.labelPos[6] == "right" ? (1) : (-1)) * bBox.width/2);
            point.dataLabel._pos.y = posY - bBox.height/2;
        }
    });
    chart.series[0].placeDataLabels();
}

$(function () {
    $('#container').highcharts({
        chart: {
            plotBackgroundColor: null,
            plotBorderWidth: null,
            plotShadow: false,
            events: {
                load: redrawDatalabels,
                redraw: redrawDatalabels
            }
        },
        title: {
            text: 'Browser market shares at a specific website, 2014'
        },
        tooltip: {
            pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
        },
        plotOptions: {
            pie: {
                allowPointSelect: true,
                cursor: 'pointer',
                dataLabels: {
                    enabled: true,
                    connectorWidth: 0,
                    format: '<b>{point.name}</b>: {point.percentage:.1f} %',
                    style: {
                        color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
                    }
                }
            }
        },
        series: [{
            type: 'pie',
            name: 'Browser share',
            data: [
                ['Firefox', 50],
                ['IE', 50],
                ['Safari', 25],
                ['Opera', 25]
            ]
        }]
    });
});

Upvotes: 2

user2345998
user2345998

Reputation: 649

It looks like that there's no build-in feature to do this. I think you have to use a negative distance, and if the chart size changes, you have to calculate the new distance to keep the labels centered on the slice.

You could handle this in the load event. Here's a simple example what you could refine to fit your needs:

http://jsfiddle.net/uhydP/317/

  events: {
        load: function(e) {
            this.options.plotOptions.series.dataLabels.distance =  (this.chartHeight / 5.5) * -1;
            this.series[0].update(this.options);
        }
    }

Upvotes: 0

Related Questions