This tutorial will explain how we can place an automatically-calculated total on a stack of columns.
Preparing value axis
Normally, the chart would not calculate totals, saving CPU for us. We need to enable it by setting calculateTotals: true
on our value axis:
let yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, { calculateTotals: true, renderer: am5xy.AxisRendererY.new(root, {}) }));
var yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, { calculateTotals: true, renderer: am5xy.AxisRendererY.new(root, {}) }));
Adding a label bullet
To place labels on or in a column, we will need to add a bullet with a Label
element in it.
Since we only want to single sum, we'll add it to the last series in stack.
We will also use bullet's locationY: 1
setting to ensure the bullet is placed at the end of the last column in stack.
series.bullets.push(function () { return am5.Bullet.new(root, { locationY: 1, sprite: am5.Label.new(root, { text: "{valueYTotal}", fill: am5.color(0x000000), centerY: am5.p100, centerX: am5.p50, populateText: true }) }); });
series.bullets.push(function () { return am5.Bullet.new(root, { locationY: 1, sprite: am5.Label.new(root, { text: "{valueYTotal}", fill: am5.color(0x000000), centerY: am5.p100, centerX: am5.p50, populateText: true }) }); });
Please note that value for text
setting: "{valueYTotal}"
.
It refers directly to column's data item values. That's where calculateTotals: true
on a value axis comes in handy: if we don't set it, this particular value is not calculated.
The calculateTotals: true
is needed for any other calculated data placeholders, like "{valueYTotalPercent}"
, if we want to use them.
NOTEWe are adding additional series with all-zero values in its data to hold the bullets. We also do not add it to legend. We do this, so that when series are toggled off in legend, the totals bullet stays on.
Bullet clipping
Since we're placing the bullet on top of the column, there might be a situation where bullet would get clipped if it goes outside of the plot area.
There are two things we can do to fight that.
Disable bullet masking
To disable bullet masking that, we need to set maskBullets: false
in settings of the series:
let series = chart.series.push(am5xy.ColumnSeries.new(root, { name: name, xAxis: xAxis, yAxis: yAxis, valueYField: fieldName, categoryXField: "year", stacked: true, maskBullets: false }));
var series = chart.series.push(am5xy.ColumnSeries.new(root, { name: name, xAxis: xAxis, yAxis: yAxis, valueYField: fieldName, categoryXField: "year", stacked: true, maskBullets: false }));
Extend axis scale
We can relatively extend value axis scale using its extraMax
setting:
var yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, { calculateTotals: true, extraMax: 0.1, renderer: am5xy.AxisRendererY.new(root, {}) }));
var series = chart.series.push(am5xy.ColumnSeries.new(root, { var yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, { calculateTotals: true, extraMax: 0.1, renderer: am5xy.AxisRendererY.new(root, {}) }));
This will expand value axis scale by 10% - just enough to fit our labels for totals.
Example
See the Pen Totals on top of stacks by amCharts team (@amcharts) on CodePen.
Totals on clustered stacks
Refer to "Totals on clustered column stacks" demo.