Search code examples
javascripthtmljqueryhighchartspie-chart

Place percentage labels inside each slice using Highcharts' 3D Pie Chart


I'm using Highcharts v9.2.2. Placing the labels on top of the slices for the regular Pie Chart works without problems, but switching to the 3D variant messes up the placement as demonstrated below:

Regular Pie chart

$(function() {

  $('#container').highcharts({
    chart: {
      type: 'pie',
      backgroundColor: 'rgba(0,0,0,0)',
      y: 100,
      options3d: {
        enabled: true,
        alpha: 65,
        fitToPlot: false,
        beta: 0
      }
    },
    title: {
      text: 'Regular Pie'
    },
    plotOptions: {
      pie: {
        y: 1,
        shadow: true,
        center: ['50%', '50%'],
        borderWidth: 0,
        showInLegend: false,
        size: '80%',
        data: [{
            "name": "First slice",
            "y": 100,
            "sliced": true
          },
          {
            "name": "Second slice",
            "y": 100,
            "sliced": true
          },
          {
            "name": "Third slice",
            "y": 70,
            "sliced": true
          },
          {
            "name": "Fourth slice",
            "y": 100,
            "sliced": true
          },
          {
            "name": "Fifth slice",
            "y": 100,
            "sliced": true
          }

        ]
      }
    },
    tooltip: {
      valueSuffix: '%'
    },
    series: [{
        type: 'pie',
        name: 'Browser share',

        dataLabels: {
          color: 'white',
          distance: -20,
          formatter: function() {
            if (this.percentage != 0) return Math.round(this.percentage) + '%';

          }
        }
      },
      {
        type: 'pie',
        name: 'Browser share',

        dataLabels: {
          connectorColor: 'grey',
          color: 'black',
          y: -10,
          softConnector: false,
          connectorWidth: 1,
          verticalAlign: 'top',
          distance: 20,
          formatter: function() {
            if (this.percentage != 0) return this.point.name;

          }
        }
      }
    ]
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<div id="container" style="min-width: 400px; height: 400px; margin: 0 auto"></div>

3D Pie Chart

$(function() {

  $('#container').highcharts({
    chart: {
      type: 'pie',
      backgroundColor: 'rgba(0,0,0,0)',
      y: 100,
      options3d: {
        enabled: true,
        alpha: 65,
        fitToPlot: false,
        beta: 0
      }
    },
    title: {
      text: '3D Pie'
    },
    plotOptions: {
      pie: {
        y: 1,
        shadow: true,
        center: ['50%', '50%'],
        borderWidth: 0,
        showInLegend: false,
        depth: 35,
        size: '80%',
        data: [{
            "name": "First slice",
            "y": 100,
            "sliced": true
          },
          {
            "name": "Second slice",
            "y": 100,
            "sliced": true
          },
          {
            "name": "Third slice",
            "y": 70,
            "sliced": true
          },
          {
            "name": "Fourth slice",
            "y": 100,
            "sliced": true
          },
          {
            "name": "Fifth slice",
            "y": 100,
            "sliced": true
          }

        ]
      }
    },
    tooltip: {
      valueSuffix: '%'
    },
    series: [{
        type: 'pie',
        name: 'Browser share',

        dataLabels: {
          color: 'white',
          distance: -20,
          formatter: function() {
            if (this.percentage != 0) return Math.round(this.percentage) + '%';

          }
        }
      },
      {
        type: 'pie',
        name: 'Browser share',

        dataLabels: {
          connectorColor: 'grey',
          color: 'black',
          y: -10,
          softConnector: false,
          connectorWidth: 1,
          verticalAlign: 'top',
          distance: 20,
          formatter: function() {
            if (this.percentage != 0) return this.point.name;

          }
        }
      }
    ]
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/highcharts-3d.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<div id="container" style="min-width: 400px; height: 400px; margin: 0 auto"></div>

Is there a way to properly do this for the 3D chart? I've tried tweaking distance in series[0].dataLabels but couldn't achieve a much better result than the provided example.


Solution

  • This behaviour occurs due to the following issue: https://github.com/highcharts/highcharts/issues/3259

    As a workaround you can move dataLabels with attr() method:

      function(chart) {
        var x, angle, centerX = chart.series[0].center[0],
          rad = chart.series[0].center[2] / 3;
        Highcharts.each(chart.series[0].data, function(p, i) {
          angle = p.angle;
          x = centerX + rad * Math.cos(angle);
          p.dataLabel.attr({
            x: x,
            'text-anchor': 'right'
          });
        })
      }
    

    Demo: https://jsfiddle.net/BlackLabel/2z4nfybg/