Labels inside Pie chart slices

Normally, Pie chart positions its slice labels in neat columns to the left and right of the pie. As a space-saving tip, this tutorial shows how to arrange them inside slices.

Base chart

See the Pen amCharts 4: Pie chart with labels within slice (1) by amCharts (@amcharts) on CodePen.24419

Target functionality

To achieve our target functionality, we're going to do this:

  • Place labels circularly around the pie;
  • Remove ticks;
  • Replace information displayed in labels to just display percent value;
  • Move labels inside slices.

Position labels circularly

As we mentioned before, labels are displayed in two columns next to a pie, by default.

To make them go around the pie, in a class Pie chart way, we're going to have to set our Pie series' alignLabels to false.

Remove ticks

This one is easy: simply set disabled = true on Pie series' tick template. (don't worry, we're going to provide code a bit later)

Replace label information

We also know that the full default label information ("Category: (xx%)") won't fit into a slice, so we're going to replace it to display just percent value, using Pie series' label template's text property.

Move labels inside slices

The labels in Pie series are of type AxisLabelCircular. Looking at its reference, we find a radius property. It means distance of the label from the base position around the circle.

It might be an absolute pixel value or percent, and it can also be negative. Setting it to a positive value will move the label away from the slice, while setting it to a negative one, will move it towards the center of the slice and inside it.

Full solution

OK, it's time to combine all of the above into a working demo:

pieSeries.ticks.template.disabled = true;
pieSeries.alignLabels = false;
pieSeries.labels.template.text = "{value.percent.formatNumber('#.0')}%";
pieSeries.labels.template.radius = am4core.percent(-40);
pieSeries.labels.template.fill = am4core.color("white");
pieSeries.ticks.template.disabled = true;
pieSeries.alignLabels = false;
pieSeries.labels.template.text = "{value.percent.formatNumber('#.0')}%";
pieSeries.labels.template.radius = am4core.percent(-40);
pieSeries.labels.template.fill = am4core.color("white");
{
  // ...
  "series": [{
    "type": "PieSeries",
    "alignLabels": false,
    "ticks": {
      "disabled": true
    },
    "labels": {
      "text": "{value.percent.formatNumber('#.0')}%",
      "radius": "-40%",
      "fill": "white"
    }
  }]
}

See the Pen amCharts 4: Pie chart with labels within slice (2) by amCharts (@amcharts) on CodePen.24419

Advanced label placement

Using label rotation

Before you go, we're going to teach you one more thing: automatically rotating labels so they are not all horizontal, but rather go in a ray-like style from the center of the pie.

For that we can use another AxisLabelCircular's property relativeRotation. Set it to a number of degrees to rotate the label relatively to the actual rotation of the slice.

pieSeries.labels.template.relativeRotation = 90;
pieSeries.labels.template.relativeRotation = 90;
{
  // ...
  "series": [{
    // ...
    "labels": {
      // ...
      "relativeRotation": 90
    }
  }]
}

See the Pen amCharts 4: Pie chart with labels within slice (3) by amCharts (@amcharts) on CodePen.24419

Selectively placing labels inside or outside slices

Placing labels inside slices is good way to save on space. However, some smaller labels might not be able to fit the label.

Luckily, we have adapters on our side.

We can use them to selectively modify radius (and just about any other setting) for the label, based on their overall percent value.

The following code defines two adapters: one for modifying radius and the other changing color for labels of slices that take less than 10% of the whole pie.

pieSeries.labels.template.adapter.add("radius", function(radius, target) {
  if (target.dataItem && (target.dataItem.values.value.percent < 10)) {
    return 0;
  }
  return radius;
});

pieSeries.labels.template.adapter.add("fill", function(color, target) {
  if (target.dataItem && (target.dataItem.values.value.percent < 10)) {
    return am4core.color("#000");
  }
  return color;
});
pieSeries.labels.template.adapter.add("radius", function(radius, target) {
  if (target.dataItem && (target.dataItem.values.value.percent < 10)) {
    return 0;
  }
  return radius;
});

pieSeries.labels.template.adapter.add("fill", function(color, target) {
  if (target.dataItem && (target.dataItem.values.value.percent < 10)) {
    return am4core.color("#000");
  }
  return color;
});
{
  // ...
  "series": [{
    // ...
    "labels": {
      // ...
      "adapter": {
        "radius": function(radius, target) {
          if (target.dataItem && (target.dataItem.values.value.percent < 10)) {
            return 0;
          }
          return radius;
        }
      },
      "fill": function(color, target) {
        if (target.dataItem && (target.dataItem.values.value.percent < 10)) {
          return am4core.color("#000");
        }
        return color;
      }
    }
  }]
}

See the Pen amCharts 4: Using adapters for label radius by amCharts (@amcharts) on CodePen.24419

Related content