Skip to content

Commit

Permalink
Funnel data labels, prevent overlapping when 'inside'
Browse files Browse the repository at this point in the history
  • Loading branch information
TorsteinHonsi committed Nov 18, 2023
1 parent 69fc2c2 commit 0d9c281
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 20 deletions.
10 changes: 8 additions & 2 deletions samples/unit-tests/series-funnel/funnel/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ QUnit.test('Funnel dataLabels', function (assert) {
const data = [
['Website visits', 5654],
['Downloads', 4064],
['Requested price list', 1987],
['Invoice sent', 1976],
['Requested price list', 198],
['Invoice sent', 197],
['Finalized', 4201]
];

Expand Down Expand Up @@ -277,6 +277,12 @@ QUnit.test('Funnel dataLabels', function (assert) {
'DataLabels centered horizontally inside the funnel (#10036)'
);

assert.deepEqual(
series.points.map(p => p.dataLabel.opacity),
[1, 1, 1, 0, 1],
'One of the data labels should be hidden by overlap detection'
);

series.update({
dataLabels: {
align: 'left'
Expand Down
4 changes: 2 additions & 2 deletions ts/Extensions/OverlappingDataLabels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ function hideOrShow(label: SVGElement, chart: Chart): boolean {

// Make sure the label is completely hidden to avoid catching clicks
// (#4362)
if (label.alignAttr && label.placed) { // data labels
if (label.alignAttr && label.placed) { // Data labels
label[
newOpacity ? 'removeClass' : 'addClass'
]('highcharts-data-label-hidden');
Expand All @@ -284,7 +284,7 @@ function hideOrShow(label: SVGElement, chart: Chart): boolean {
complete
);
fireEvent(chart, 'afterHideOverlappingLabel');
} else { // other labels, tick labels
} else { // Other labels, tick labels
label.attr({
opacity: newOpacity
});
Expand Down
33 changes: 17 additions & 16 deletions ts/Series/Funnel/FunnelSeries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,19 +158,21 @@ class FunnelSeries extends PieSeries {
const series = point.series,
reversed = series.options.reversed,
dlBox = point.dlBox || point.shapeArgs,
align = options.align,
verticalAlign = options.verticalAlign,
{ align, padding = 0, verticalAlign } = options,
inside =
((series.options || {}).dataLabels || {}).inside,
centerY = series.center[1],
plotY = point.plotY || 0,
pointPlotY = (
reversed ?
2 * centerY - (point.plotY as any) :
point.plotY
2 * centerY - plotY :
plotY
),
// #16176: Only SVGLabel has height set
dataLabelHeight = dataLabel.height ?? dataLabel.getBBox().height,
widthAtLabel = series.getWidthAt(
(pointPlotY as any) - dlBox.height / 2 +
(dataLabel as any).height
pointPlotY - dlBox.height / 2 +
dataLabelHeight
),
offset = verticalAlign === 'middle' ?
(dlBox.topWidth - dlBox.bottomWidth) / 4 :
Expand All @@ -179,17 +181,10 @@ class FunnelSeries extends PieSeries {
let y = dlBox.y,
x = dlBox.x;

// #16176: Only SVGLabel has height set
const dataLabelHeight = pick(
dataLabel.height,
dataLabel.getBBox().height
);

if (verticalAlign === 'middle') {
y = dlBox.y - dlBox.height / 2 + dataLabelHeight / 2;
} else if (verticalAlign === 'top') {
y = dlBox.y - dlBox.height + dataLabelHeight +
(options.padding || 0);
y = dlBox.y - dlBox.height + dataLabelHeight + padding;
}

if (
Expand All @@ -198,9 +193,9 @@ class FunnelSeries extends PieSeries {
verticalAlign === 'middle'
) {
if (align === 'right') {
x = dlBox.x - (options.padding as any) + offset;
x = dlBox.x - padding + offset;
} else if (align === 'left') {
x = dlBox.x + (options.padding as any) - offset;
x = dlBox.x + padding - offset;
}
}

Expand All @@ -212,6 +207,12 @@ class FunnelSeries extends PieSeries {
};

options.verticalAlign = 'bottom';
if (inside) {
// If the distance were positive (as default), the overlapping
// labels logic would skip these labels and they would be allowed
// to overlap.
options.distance = void 0;
}

// Call the parent method
if (inside && point.visible) {
Expand Down

0 comments on commit 0d9c281

Please sign in to comment.