Search code examples
javascriptchart.jsheightstacked-bar-chart

Min. height for stacked bar chartjs


I've a vertically stacked bar chart in chart.js. Since the bars are being generated based on some userinput, it's possible that I get a chart that would look something like this:

Example

I want to enforce a minimum height for each stack to ensure that even small values are displayed more clearly.

In my current approach I'm checking if the height of a stack is below a certain value and then increase it's height with getProps(). The problem here is that even though the height is correctly set, the corresponding stack isn't being updated.

{
    id: 'ExtraHeightPlugin',
    afterDatasetsDraw: (chart: Chart <ChartType>) => {
        chart.data.labels.forEach((label, index) => {
            chart.data.datasets.forEach((dataset, datasetIndex) => {
                let currentStackHeight: number = chart.getDatasetMeta(datasetIndex).data[index].getProps(['height'])['height'];
                if (currentStackHeight> 0 && currentStackHeight< 35) {
                    currentStackHeight+= 35;
                    chart.getDatasetMeta(datasetIndex).data[index].getProps(['height'])['height'] = currentStackHeight;
                }
            });
        });
    }
}

Any help would be greatly appreciated.


Solution

  • getProps() only retrieves properties and doesn't set them.

     const minStackHeightPlugin = {
      id: 'minStackHeightPlugin',
      afterDatasetsDraw: (chart, args, options) => {
        const minHeight = options.minHeight || 35;
        
        chart.data.labels.forEach((label, index) => {
          chart.data.datasets.forEach((dataset, datasetIndex) => {
            const meta = chart.getDatasetMeta(datasetIndex);
            if (!meta.hidden) {
              const dataItem = meta.data[index];
              const height = dataItem.height;
              
              if (height > 0 && height < minHeight) {
                // Store original height for tooltip and other calculations
                if (!dataItem._originalHeight) {
                  dataItem._originalHeight = height;
                }
                
                // Calculate Y adjustment to keep the bar anchored correctly
                const yAdjustment = (minHeight - height) / 2;
                
                // Update the visual properties
                dataItem.height = minHeight;
                dataItem.y -= yAdjustment;
              }
            }
          });
        });
      },