This tutorial will explain how you can deal with very long axis labels, by wrapping and/or truncating them.
Prerequisites
If you haven't done that already, we suggest you take a look at the "Positioning Axis Elements" article, which explains the principles about configuring Axis elements, including the concept of "axis renderer". Moving forward we will assume you are familiar with the idea, that almost every appearance setting for an axis is added via its renderer
property.
Furthermore, this tutorial also uses "list templates". Make sure you take a brief look at the "List templates" article for an introduction to this powerful concept.
Base chart
Let's start off with a basic chart, that has very long labels on its Category axis:
See the Pen amCharts V4: Axis label wrapping and truncation (1) by amCharts (@amcharts) on CodePen.24419
Looks cool? Not really.
Let's see how we can fix that.
Wrapping labels
The first solution that comes into mind is: "let's make labels wrap so they are not overlapping".
To make that happen, we will need to modify axis label template object. For an axis, this template is stored in its Renderer: axis.renderer.labels.template
.
An axis label is an object of type Label
. Click the link on it to explore it's all options.
For now, to make our labels wrap we will need its two options: wrap
and maxWidth
.
The first one is obvious - it's a boolean setting indicating whether labels should wrap. The second gives a width threshold for the label, so that it knows how much width it has available.
Let's try it:
let label = categoryAxis.renderer.labels.template; label.wrap = true; label.maxWidth = 120;
var label = categoryAxis.renderer.labels.template; label.wrap = true; label.maxWidth = 120;
{ // ... "xAxes": [{ // ... "renderer": { "labels": { "wrap": true, "maxWidth": 120 } } }] }
See the Pen amCharts V4: Axis label wrapping and truncation (2) by amCharts (@amcharts) on CodePen.24419
NOTE The maxWidth
here simply tells the label to not grow beyond certain number of pixels. The label will automatically wrap on this set threshold.
Truncating labels
Basic usage
Wrapping labels made them readable, but they also made them tall, resulting in chart itself being flattened next to nothing. Not particularly good.
Let's try to make labels auto-truncate.
We'll still need to set the maximum width of the label using maxWidth
. However, instead of telling it to wrap, we'll tell it to truncate the text by setting its truncate
property.
let label = categoryAxis.renderer.labels.template; label.truncate = true; label.maxWidth = 120;
var label = categoryAxis.renderer.labels.template; label.truncate = true; label.maxWidth = 120;
{ // ... "xAxes": [{ // ... "renderer": { "labels": { "truncate": true, "maxWidth": 120 } } }] }
See the Pen amCharts V4: Axis label wrapping and truncation (3) by amCharts (@amcharts) on CodePen.24419
Now, as we say here "the wolf is fed, yet the sheep is alive". We don't sacrifice the height of the chart itself, yet we retain part of the labels, giving users an idea of what this category is about.
Modifying ellipsis
By default, labels are truncated with a triple-dot for an ellipsis. You can use label's ellipsis
property to set it to any other string.
Displaying tooltips
Now that we have truncated the labels, we are concealing part of the information from our users.
Let's set the labels up to display a tooltip when user rolls over the label with a mouse cursor or taps it on a touch screen.
Any element in amCharts 4 has a property tooltipText
. If it's set, a tooltip will appear when hovering the element.
We can set it to some static text, or we can use dynamic placeholders, that can draw data from related data item and even elements own properties and data. Since we know Category axis' labels have data item with a category
property, we can use the placeholder "{category}"
in label template's tooltipText
:
let label = categoryAxis.renderer.labels.template; label.truncate = true; label.maxWidth = 120; label.tooltipText = "{category}";
var label = categoryAxis.renderer.labels.template; label.truncate = true; label.maxWidth = 120; label.tooltipText = "{category}";
{ // ... "xAxes": [{ // ... "renderer": { "labels": { "truncate": true, "maxWidth": 120, "tooltipText": "{category}" } } }] }
That's it. Now hovering over the label will display full text of the truncated label. Go ahead, try it out on a below chart:
See the Pen amCharts V4: Axis label wrapping and truncation (4) by amCharts (@amcharts) on CodePen.24419
Labels are too big even for a tooltip? Let's fix that by constraining tooltip width and making it auto-wrap:
categoryAxis.tooltip.label.maxWidth = 200; categoryAxis.tooltip.label.wrap = true;
categoryAxis.tooltip.label.maxWidth = 200; categoryAxis.tooltip.label.wrap = true;
{ // ... "xAxes": [{ // ... "tooltip": { "label": { "maxWidth": 200, "wrap": true } } }] }
Auto-fitting labels
All of the above solutions involved hard-coded maxWidth
value.
Let's take it one step further and make it fully automatic: so that maxWidth
is always set to actual available space.
For that we are going to be utilizing axis' sizechanged
event, which kicks in whenever axis size changes.
When that happens we will calculate actual width in pixels, take into account how many categories are there on the screen right now, and div it all up to find out a perfect maxWidth
.
categoryAxis.events.on("sizechanged", function(ev) {
let axis = ev.target;
let cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
axis.renderer.labels.template.maxWidth = cellWidth;
});
categoryAxis.events.on("sizechanged", function(ev) {
var axis = ev.target;
var cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
axis.renderer.labels.template.maxWidth = cellWidth;
});
{
// ...
"xAxes": [{
// ...
"events": {
"sizechanged": function(ev) {
var axis = ev.target;
var cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
axis.renderer.labels.template.maxWidth = cellWidth;
}
}
}]
}
Now, whatever data you throw at the chart, it will adapt and crop the labels accordingly:
See the Pen amCharts V4: Axis label wrapping and truncation (4) by amCharts team (@amcharts) on CodePen.0
(Try to open the above chart in a new window and play around with its size)
Auto-rotating labels
Building on the previous example, let's make the sizechanged
event work to automatically rotate labels if they do not fit into specific cell width.
categoryAxis.events.on("sizechanged", function(ev) { let axis = ev.target; var cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex); if (cellWidth < axis.renderer.labels.template.maxWidth) { axis.renderer.labels.template.rotation = -45; axis.renderer.labels.template.horizontalCenter = "right"; axis.renderer.labels.template.verticalCenter = "middle"; } else { axis.renderer.labels.template.rotation = 0; axis.renderer.labels.template.horizontalCenter = "middle"; axis.renderer.labels.template.verticalCenter = "top"; } });
categoryAxis.events.on("sizechanged", function(ev) { var axis = ev.target; var cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex); if (cellWidth < axis.renderer.labels.template.maxWidth) { axis.renderer.labels.template.rotation = -45; axis.renderer.labels.template.horizontalCenter = "right"; axis.renderer.labels.template.verticalCenter = "middle"; } else { axis.renderer.labels.template.rotation = 0; axis.renderer.labels.template.horizontalCenter = "middle"; axis.renderer.labels.template.verticalCenter = "top"; } });
{ // ... "xAxes": [{ // ... "events": { "sizechanged": function(ev) { var axis = ev.target; var cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex); if (cellWidth < axis.renderer.labels.template.maxWidth) { axis.renderer.labels.template.rotation = -45; axis.renderer.labels.template.horizontalCenter = "right"; axis.renderer.labels.template.verticalCenter = "middle"; } else { axis.renderer.labels.template.rotation = 0; axis.renderer.labels.template.horizontalCenter = "middle"; axis.renderer.labels.template.verticalCenter = "top"; } } } }] }
See the Pen amCharts V4: Axis label wrapping and truncation (5) by amCharts team (@amcharts) on CodePen.24419
Zooming axes
So far we have been using sizechanged
event to resize labels when actual width of the chart container changed.
However, zooming the axis would also change number and thus available width for the labels, too.
So, to handle both events, we should execute our label sizing code on axis' startendchanged
event, as well.