CurveChart (or a TimeLine) is a new exciting chart product, allowing twisting and bending the charts into any custom shape. This tutorial will show how you can make labels of a curved axis follow its angle.
Base chart
Let's start with a basic chart example we took from our "TimeLine Chart" article:
See the Pen amCharts 4: Curve chart by amCharts team (@amcharts) on CodePen.24419
The X axis is bent according to our points. However its labels, while positioned correctly, are all statically horizontal.
Let's see how we can make them gently follow the curve.
Solution
The solution comes in form of an adapter.
Basically an adapter is a way to define a custom function that would override value of any property for any object. (read more about adapters)
In this case we'll need to override axis labels' rotation
property.
categoryAxis.renderer.labels.template.adapter.add("rotation", function (rotation, target) { let value = target.dataItem.category; let position = categoryAxis.categoryToPosition(value); let angle = categoryAxis.renderer.positionToAngle(position) - 90; return angle; });
categoryAxis.renderer.labels.template.adapter.add("rotation", function (rotation, target) { var value = target.dataItem.category; var position = categoryAxis.categoryToPosition(value); var angle = categoryAxis.renderer.positionToAngle(position) - 90; return angle; });
{ // ... "xAxes": [{ // ... "renderer": { "labels": { "adapter": { "rotation": function (rotation, target) { var categoryAxis = target.baseSprite.xAxes.getIndex(0); var value = target.dataItem.category; var position = categoryAxis.categoryToPosition(value); var angle = categoryAxis.renderer.positionToAngle(position) - 90; return angle; }); } } } }] }
See the Pen amCharts 4: Curve chart by amCharts team (@amcharts) on CodePen.24419
The above example uses CategoryAxis
as an X axis. In order to find label's relative position within axis, we used CategoryAxis
' method categoryToPosition(category)
.
Naturally, for other axis types, other methods would need to be used.
ValueAxis
would use valueToPosition(value)
:
valueAxis.renderer.labels.template.adapter.add("rotation", function (rotation, target) { let value = target.dataItem.value; let position = valueAxis.valueToPosition(value); let angle = valueAxis.renderer.positionToAngle(position) - 90; return angle; });
categoryAxis.renderer.labels.template.adapter.add("rotation", function (rotation, target) { var value = target.dataItem.value; var position = categoryAxis.valueToPosition(value); var angle = categoryAxis.renderer.positionToAngle(position) - 90; return angle; });
{ // ... "xAxes": [{ // ... "renderer": { "labels": { "adapter": { "rotation": function (rotation, target) { var valueAxis = target.baseSprite.xAxes.getIndex(0); var value = target.dataItem.value; var position = valueAxis.valueToPosition(value); var angle = valueAxis.renderer.positionToAngle(position) - 90; return angle; }); } } } }] }
While DateAxis
would use dateToPosition(date)
:
dateAxis.renderer.labels.template.adapter.add("rotation", function (rotation, target) { let value = target.dataItem.date; let position = dateAxis.dateToPosition(value); let angle = dateAxis.renderer.positionToAngle(position) - 90; return angle; });
dateAxis.renderer.labels.template.adapter.add("rotation", function (rotation, target) { var value = target.dataItem.date; var position = dateAxis.dateToPosition(value); var angle = dateAxis.renderer.positionToAngle(position) - 90; return angle; });
{ // ... "xAxes": [{ // ... "renderer": { "labels": { "adapter": { "rotation": function (rotation, target) { var dateAxis = target.baseSprite.xAxes.getIndex(0); var value = target.dataItem.date; var position = dateAxis.dateToPosition(value); var angle = dateAxis.renderer.positionToAngle(position) - 90; return angle; }); } } } }] }