Hello everyone! I'm encountering a small problem called 'align', it's giving me a headache to resolve and I would like the help of the guys or a possible improvement.
Well, my situation is as follows, I have a set of values, but some of them are close values and one stands on top of the other, so my idea was to align one for 'start' and the other the opposite and vice versa, and by default the center.
But I am not able to do this calculation, it follows my code attempt:
this.options.plugins.datalabels.align = function (context) {
self.lastDataLabel.pos = 'center'
if (context.dataIndex === self.lastDataLabel.dtIndex ||
(context.dataset.data[context.dataIndex] - 10 > context.dataset.data[self.lastDataLabel.dtIndex])
) {
self.lastDataLabel.pos = 'start'
} else if (context.dataset.data[context.dataIndex] - 10 < context.dataset.data[self.lastDataLabel.dtIndex]) {
self.lastDataLabel.pos = 'end'
}
self.lastDataLabel.value = context.dataset.data[context.dataIndex]
self.lastDataLabel.dtIndex = context.dataIndex
self.lastDataLabel.dtsIndex = context.datasetIndex
return self.lastDataLabel.pos
}
My dataset:
"datasets": [
{
"label": "CAND. A",
"backgroundColor": "rgb(8, 81, 156)",
"borderColor": "rgb(8, 81, 156)",
"type": "line",
"pointRadius": "5",
"pointHoverRadius": "5",
"fill": false,
"hidden": false,
"data": [
"10",
"20",
"30",
"40"
]
},
{
"label": "CAND. B",
"backgroundColor": "rgb(166, 54, 3)",
"borderColor": "rgb(166, 54, 3)",
"type": "line",
"pointRadius": "5",
"pointHoverRadius": "5",
"fill": false,
"hidden": false,
"data": [
"20",
"20",
"25",
"18"
]
},
{
"label": "CAND. C",
"backgroundColor": "rgb(0, 109, 44)",
"borderColor": "rgb(0, 109, 44)",
"type": "line",
"pointRadius": "5",
"pointHoverRadius": "5",
"fill": false,
"hidden": false,
"data": [
"70",
"60",
"45",
"42"
]
}
],
"labels": [
"AGO",
"SET",
"OUT",
"NOV"
]
Here's a print of how it's getting:

And how I wish it were:

My config:
"chart.js": "2.7.2",
"chartjs-plugin-datalabels": "0.3.0",
@renatodolce sorry for the late reply: unfortunately there is nothing built-in to prevent label to overlap. I'm currently looking how to implement this feature, but that's not trivial.
As a (very limited) workaround (and if you don't have more that 3 datasets), you can still script the align option to detect where the label should be positioned. Something similar to what I did in this example:
align: function(ctx) {
var idx = ctx.dataIndex;
var val = ctx.dataset.data[idx];
var datasets = ctx.chart.data.datasets;
var min, max, i, ilen, ival;
min = max = val;
for (i = 0, ilen = datasets.length; i < ilen; ++i) {
if (i === ctx.datasetIndex) {
continue;
}
ival = datasets[i].data[idx];
min = Math.min(min, ival);
max = Math.max(max, ival);
if (val > min && val < max) {
return 'center';
}
}
return val <= min ? 'start' : 'end';
}
you can see it in action in this jsfiddle. It's not ideal, but I think it works in most use cases where the number of datasets is <= 3.
I'm not sure that tweaking the align option to prevent labels to overlap would work in many cases, especially if there is more than 3 datasets. Prevent overlap by moving the label position is already reported in #72 (and a few others), so I'm closing this issue.
Most helpful comment
@renatodolce sorry for the late reply: unfortunately there is nothing built-in to prevent label to overlap. I'm currently looking how to implement this feature, but that's not trivial.
As a (very limited) workaround (and if you don't have more that 3 datasets), you can still script the
alignoption to detect where the label should be positioned. Something similar to what I did in this example:you can see it in action in this jsfiddle. It's not ideal, but I think it works in most use cases where the number of datasets is <= 3.