From dff44828db94467f153a5da22b464317fcb3bcca Mon Sep 17 00:00:00 2001 From: Hyun-je Alex Moon Date: Wed, 27 Dec 2023 15:18:14 +0900 Subject: [PATCH] fix(#11615): fix calculating caretX position on stacked bar with index interaction. (#11616) --- src/plugins/plugin.tooltip.js | 8 +++-- test/specs/plugin.tooltip.tests.js | 56 ++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/plugins/plugin.tooltip.js b/src/plugins/plugin.tooltip.js index 05b5fb947..e76b1479e 100644 --- a/src/plugins/plugin.tooltip.js +++ b/src/plugins/plugin.tooltip.js @@ -24,7 +24,7 @@ const positioners = { } let i, len; - let x = 0; + let xSet = new Set(); let y = 0; let count = 0; @@ -32,14 +32,16 @@ const positioners = { const el = items[i].element; if (el && el.hasValue()) { const pos = el.tooltipPosition(); - x += pos.x; + xSet.add(pos.x); y += pos.y; ++count; } } + const xAverage = [...xSet].reduce((a, b) => a + b) / xSet.size; + return { - x: x / count, + x: xAverage, y: y / count }; }, diff --git a/test/specs/plugin.tooltip.tests.js b/test/specs/plugin.tooltip.tests.js index 3314ce138..69e8c7f64 100644 --- a/test/specs/plugin.tooltip.tests.js +++ b/test/specs/plugin.tooltip.tests.js @@ -1088,6 +1088,62 @@ describe('Plugin.Tooltip', function() { expect(Object.prototype.hasOwnProperty.call(fn.calls.first().args[1], 'y')).toBe(true); expect(fn.calls.first().object instanceof Tooltip).toBe(true); }); + + it('Should ignore same x position when calculating average position with index interaction on stacked bar', async function() { + var chart = window.acquireChart({ + type: 'bar', + data: { + datasets: [{ + label: 'Dataset 1', + data: [10, 20, 30], + pointHoverBorderColor: 'rgb(255, 0, 0)', + pointHoverBackgroundColor: 'rgb(0, 255, 0)', + stack: 'stack1', + }, { + label: 'Dataset 2', + data: [40, 40, 40], + pointHoverBorderColor: 'rgb(0, 0, 255)', + pointHoverBackgroundColor: 'rgb(0, 255, 255)', + stack: 'stack1', + }, { + label: 'Dataset 3', + data: [90, 100, 110], + pointHoverBorderColor: 'rgb(0, 0, 255)', + pointHoverBackgroundColor: 'rgb(0, 255, 255)' + }], + labels: ['Point 1', 'Point 2', 'Point 3'] + }, + options: { + interaction: { + mode: 'index' + }, + plugins: { + position: 'average', + }, + } + }); + + // Trigger an event over top of the + var pointIndex = 1; + var datasetIndex = 0; + var meta = chart.getDatasetMeta(datasetIndex); + var point = meta.data[pointIndex]; + await jasmine.triggerMouseEvent(chart, 'mousemove', point); + + var tooltipModel = chart.tooltip; + const activeElements = tooltipModel.getActiveElements(); + + const xPositionArray = activeElements.map((element) => element.element.x); + const xPositionArrayAverage = xPositionArray.reduce((a, b) => a + b) / xPositionArray.length; + + const xPositionSet = new Set(xPositionArray); + const xPositionSetAverage = [...xPositionSet].reduce((a, b) => a + b) / xPositionSet.size; + + expect(xPositionArray.length).toBe(3); + expect(xPositionSet.size).toBe(2); + expect(tooltipModel.caretX).not.toBe(xPositionArrayAverage); + expect(tooltipModel.caretX).toBe(xPositionSetAverage); + }); }); it('Should avoid tooltip truncation in x axis if there is enough space to show tooltip without truncation', async function() {