]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
fix(#11615): fix calculating caretX position on stacked bar with index interaction...
authorHyun-je Alex Moon <smoonsf@gmail.com>
Wed, 27 Dec 2023 06:18:14 +0000 (15:18 +0900)
committerGitHub <noreply@github.com>
Wed, 27 Dec 2023 06:18:14 +0000 (07:18 +0100)
src/plugins/plugin.tooltip.js
test/specs/plugin.tooltip.tests.js

index 05b5fb9470d040b2abb8b80584bb321c359550c7..e76b1479e06d05f49da0cb276390013365cf819a 100644 (file)
@@ -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
     };
   },
index 3314ce1385d4295188e8b64f143eadbcc6fb71ed..69e8c7f64c9952edc28d22b5ba323163f12f8d9f 100644 (file)
@@ -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() {