chartjs-plugin-datalabels icon indicating copy to clipboard operation
chartjs-plugin-datalabels copied to clipboard

Request: add setting to show all labels above stacked bar

Open Creatium opened this issue 4 years ago • 1 comments

Hi,

So I'm working on this project, where I'm showing percentages of stacked bar inside the bar. But when the bar is small, the text gets clipped or is not visible. So I figured those numbers should be put outside of the bar and colored based on the dataset. Having in mind all the alignment and anchoring options that this plugin has, an option to put labels outside of stacked bar should be implemented too.

Note: setting anchor: 'end' only puts the top bar label outside, and the one below move to the top one.

In the best case scenario it should work as follows:

  • transfer both labels outside the stacked bar, when the height is limited (can be set by user maybe);
  • make sure that both labels are in relation with each other, so they have same spacing and don't flow over each other;

The simplified version would simply add anchor: 'outside' setting and could leave all else for the user to set via functions.

Here is an image sample: Screenshot 2021-06-01 195106

This is the way I made this:

anchor: context => {
    let bar = context.chart.getDatasetMeta(context.datasetIndex).data[context.dataIndex];
    let barHeight = Math.abs(bar.y-bar.base);
    const threshold = 7;
    if (barHeight < threshold) {
        return 'end';
    }
    return 'center';
}

In this code what I do is:

  1. get the bar data;
  2. calculate bar height from .y and .base params (height param is undefined);
  3. set threshold (minimum height);
  4. check for threshold.

Issue with this code is that it sets the lower bar label on the top bar, not above both bars. So I also use pretty much same code for offset, to calculate the height of top bar and offset first label by that height. Its a mess and does not work perfectly (spacing is off for different height bars). But a start.

offset: context => {
    let bar = context.chart.getDatasetMeta(1).data[context.dataIndex];
    let barHeight = Math.abs(bar.y-bar.base);
    let offset = 10;
    offset += barHeight;
    return offset;
}

P.S. ChartJS 3, Datalabels 2.0 RC

Creatium avatar Jun 01 '21 17:06 Creatium

In the best case scenario it should work as follows: ...

I don't think this plugin should implement such a very specific (and complex) behavior that only produces your use case. It would require to introduce more and more options to accommodate all designs, which goes against what I want for this plugin API.

The simplified version would simply add anchor: 'outside' setting and could leave all else for the user to set via functions.

This approach is better, however it must be generic and work with all type of scales and elements. That means this plugin should not have to test if it's a bar chart with a linear scale which is stacked. 'outside' is not a good name because it doesn't tell where: "outside the current element", "outside, after the last element", "outside, before the first element", ... Maybe data-min and data-max would be better (not sure I like these names, will need to think more).

Until there is a proper way, an alternative solution to implement your design could be to use multiple labels and only display the ones on the last bar, for example: https://codepen.io/simonbrunel/pen/GRWyLpx

simonbrunel avatar Jun 01 '21 20:06 simonbrunel