Search code examples
labelresponsiveamchartsfont-sizeamcharts4

AmCharts4 Responsive Label Sizing


I'm trying to create a gauge that has a single label which can be selected by the user when clicking on a range. The label itself should stay at a consistent size with the rest of the chart.

I can't find a way to do this in AmCharts4 natively, but wondering if it could be combined with the solution here https://css-tricks.com/fitting-text-to-a-container/#just-use-svg

https://codepen.io/ChazUK/pen/ExyJdzY

const label = chart.radarContainer.createChild(am4core.Label);
label.isMeasured = false;
label.fontSize = '2rem';
label.x = am4core.percent(50);
label.horizontalCenter = 'middle';
label.verticalCenter = 'bottom';

This is how I want the text to behave, with the font taking up the same ratio.


Solution

  • I've found a solution. The key is scaling the label when the chart changes size. A demo was provided in the docs https://www.amcharts.com/docs/v4/tutorials/automatically-resize-label-to-fit-donut-inner-radius/, but this made the font fit a width and not stay a consistent size, so the scale needed to be linked to the height rather than width.

    const chart = am4core.create('chart', am4charts.GaugeChart);
    
    ...
    
    /*
     * Create Container to hold responsive label
     * Height dictates the font size
     */
    const container = chart.createChild(am4core.Container);
    container.horizontalCenter = 'middle';
    container.verticalCenter = 'bottom';
    container.height = am4core.percent(20);
    container.x = am4core.percent(50);
    container.y = am4core.percent(100);
    container.isMeasured = false;
    
    /*
     * Create the label as a child of container
     */
    const label = container.createChild(am4core.Label);
    label.horizontalCenter = 'middle';
    label.verticalCenter = 'bottom';
    label.x = am4core.percent(50);
    label.y = am4core.percent(100);
    label.fontSize = 30; // irrelevant, can be omitted
    label.text = 'Auto sizing text';
    
    /*
     * Update the scale of the label on the
     * sizechanged event
     */
    chart.events.on('sizechanged', () => {
      label.scale = container.bbox.height / this.label.bbox.height;
    });