Search code examples
amchartsamcharts5

amCharts 5: Auto-adjusting chart height based on a number of data items


I am trying to replicate amCharts 4 Auto-adjusting chart height based on a number of data items with amCharts 5 instead.

I already asked a question on Stack Overflow to understand how amCharts 5 returns the height of an axis that has not been drawn yet. No answer so far.

The best I have come so far is with:

// Note: before first render, axis.height() returns erroneous value so the following hack fixes the problem but it assumes an initial root height of 300px
function getAxisHeight(axis: am5xy.CategoryAxis<am5xy.AxisRendererY>) {
  let height = 198.2;

  if (axis.inited) {
    height = axis.height();
  }

  return height;
}

function addAutoHeight(
  root: am5.Root,
  categoryAxis: am5xy.CategoryAxis<am5xy.AxisRendererY>,
  columnSize: number
) {
  categoryAxis.events.on("datavalidated", function (ev) {
    const axis = ev.target;

    const totalColumnSize = axis.data.length * columnSize;
    const adjustHeight = totalColumnSize - getAxisHeight(axis);
    const targetHeight = root.height() + adjustHeight;

    root.dom.style.height = targetHeight + "px";
  });
}

So, can we auto-adjust the chart height based on a number of data items with amCharts 5 without dirty hacks like above? If yes, what settings, event handlers, … allows that?


Solution

  • With the help of the new amCharts 5 Auto-adjusting chart height based on a number of data items tutorial, this is what works for me:

    function addAutoHeight(
      categoryAxis: am5xy.CategoryAxis<am5xy.AxisRendererY>,
      columnSize: number
    ) {
      categoryAxis.events.on("datavalidated", function (ev) {
        const yAxis = ev.target;
        const chart = yAxis.chart;
    
        if (chart) {
          // a title was added on top of the chart
          const titleHeight = chart.children.getIndex(0)?.height() ?? 0;
    
          const height =
            chart.get("paddingTop", 0) +
            titleHeight +
            chart.topAxesContainer.height() +
            yAxis.data.length * columnSize +
            chart.bottomAxesContainer.height() +
            chart.get("paddingBottom", 0);
    
          chart.root.dom.style.height = height + "px";
        }
      });
    }
    

    The event is attached to the axis and not the series because only the values in the axis matter.