My problem: i would like to find an automatic way to center labels in donut chart cells. In my case each cells contains an array of complex objects, what i want is to show the number of those objects.
Playing with radius, allowed me to find those values:
I applied it as a quick fix but i don't like this solution, as it's fixed for 4 layers (what if I need to add an other layer ? etc....) and using "magic numbers" is unmaintenable...
Do you have a better solution ?
You can test it here: https://jsfiddle.net/aliz/gwz7om9e/
Line 40:
pieSeries.labels.template.radius = am4core.percent(positionRadiusInPie);
Note: Using those attributes didn't work: "horizontalCenter", "VerticalCenter", "textAlign", "align".
EDIT: response to Bhavik Kalariya
You can at least get it down to just using one base constant of your choosing by using an adapter approach on the label's radius
to calculate the value you want for each series that is added to the chart using whatever formula you choose. Here's a basic formula that gave good results for me with your setup, where BASE_INNER_LABEL_RADIUS
is set to -45.
pieSeries.labels.template.adapter.add('radius', function(radius, target) {
var chart = target.baseSprite; //chart stored in baseSprite of the AxisCircularLabel
var index = chart.series.indexOf(target.dataItem.component); //corresponding series stored in the dataItem's component
return am4core.percent(BASE_INNER_LABEL_RADIUS / (index + 2)); //Uses singular constant defined elsewhere, which is used in all series
});
This will adjust itself according to the number of series you add to the chart. You can make this as robust as you want by making further tweaks if you have fewer series and want to make the labels even more centered.
Edit
If you want to be even more generic, you can get at the slice sprite directly through the target.dataItem.sprites
array (typically the first element, though you can loop through and look for an object whose className
is "Slice"
if you want to be super safe about it) and calculate your desired radius value using any of the numeric properties it has, such as innerRadius
.
pieSeries.labels.template.adapter.add('radius', function(radius, target) {
var chart = target.baseSprite; //chart stored in baseSprite of the AxisCircularLabel
var index = chart.series.indexOf(target.dataItem.component); //corresponding series stored in the dataItem's component
return -(target.dataItem.sprites[0].innerRadius) / (index + 3);
});
You'll want to adjust this accordingly, of course.