]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Fix controller.getMinMax for stacked charts (#9766)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Wed, 13 Oct 2021 21:24:38 +0000 (00:24 +0300)
committerGitHub <noreply@github.com>
Wed, 13 Oct 2021 21:24:38 +0000 (00:24 +0300)
src/core/core.datasetController.js
test/fixtures/controller.line/stacking/bounds-data.png
test/specs/controller.line.tests.js

index 584aeda027e14c8255ca3721200e9db8910ded5f..63aea1f33ad31a634424e688ed7c1ba8caba1628 100644 (file)
@@ -67,7 +67,7 @@ function getSortedDatasetIndices(chart, filterVisible) {
   return keys;
 }
 
-function applyStack(stack, value, dsIndex, options) {
+function applyStack(stack, value, dsIndex, options = {}) {
   const keys = stack.keys;
   const singleMode = options.mode === 'single';
   let i, ilen, datasetIndex, otherValue;
@@ -212,6 +212,8 @@ function clearStacks(meta, items) {
 
 const isDirectUpdateMode = (mode) => mode === 'reset' || mode === 'none';
 const cloneIfNotShared = (cached, shared) => shared ? cached : Object.assign({}, cached);
+const createStack = (canStack, meta, chart) => canStack && !meta.hidden && meta._stacked
+  && {keys: getSortedDatasetIndices(chart, true), values: null};
 
 export default class DatasetController {
 
@@ -567,11 +569,7 @@ export default class DatasetController {
     const values = stack && parsed._stacks[scale.axis];
     if (stack && values) {
       stack.values = values;
-      // Need to consider individual stack values for data range,
-      // in addition to the stacked value
-      range.min = Math.min(range.min, value);
-      range.max = Math.max(range.max, value);
-      value = applyStack(stack, parsedValue, this._cachedMeta.index, {all: true});
+      value = applyStack(stack, parsedValue, this._cachedMeta.index);
     }
     range.min = Math.min(range.min, value);
     range.max = Math.max(range.max, value);
@@ -586,16 +584,15 @@ export default class DatasetController {
     const sorted = meta._sorted && scale === meta.iScale;
     const ilen = _parsed.length;
     const otherScale = this._getOtherScale(scale);
-    const stack = canStack && meta._stacked && {keys: getSortedDatasetIndices(this.chart, true), values: null};
+    const stack = createStack(canStack, meta, this.chart);
     const range = {min: Number.POSITIVE_INFINITY, max: Number.NEGATIVE_INFINITY};
     const {min: otherMin, max: otherMax} = getUserBounds(otherScale);
-    let i, value, parsed, otherValue;
+    let i, parsed;
 
     function _skip() {
       parsed = _parsed[i];
-      value = parsed[scale.axis];
-      otherValue = parsed[otherScale.axis];
-      return !isFinite(value) || otherMin > otherValue || otherMax < otherValue;
+      const otherValue = parsed[otherScale.axis];
+      return !isFinite(parsed[scale.axis]) || otherMin > otherValue || otherMax < otherValue;
     }
 
     for (i = 0; i < ilen; ++i) {
index 90ce6a30c282c7f2dbec6a7934fdc828ab3b3219..71ea7e96392b8cdb1785cd76785e0549ff1ab74d 100644 (file)
Binary files a/test/fixtures/controller.line/stacking/bounds-data.png and b/test/fixtures/controller.line/stacking/bounds-data.png differ
index 7210367ca95e0c2fc0026444330429770149e69b..684b1919bb24edc5f7160bec8b0cb7dde290f0b0 100644 (file)
@@ -59,6 +59,32 @@ describe('Chart.controllers.line', function() {
     expect(createChart).not.toThrow();
   });
 
+  it('should find min and max for stacked chart', function() {
+    var chart = window.acquireChart({
+      type: 'line',
+      data: {
+        datasets: [{
+          data: [10, 11, 12, 13]
+        }, {
+          data: [1, 2, 3, 4]
+        }],
+        labels: ['a', 'b', 'c', 'd']
+      },
+      options: {
+        scales: {
+          y: {
+            stacked: true
+          }
+        }
+      }
+    });
+    expect(chart.getDatasetMeta(0).controller.getMinMax(chart.scales.y, true)).toEqual({min: 10, max: 13});
+    expect(chart.getDatasetMeta(1).controller.getMinMax(chart.scales.y, true)).toEqual({min: 11, max: 17});
+    chart.hide(0);
+    expect(chart.getDatasetMeta(0).controller.getMinMax(chart.scales.y, true)).toEqual({min: 10, max: 13});
+    expect(chart.getDatasetMeta(1).controller.getMinMax(chart.scales.y, true)).toEqual({min: 1, max: 4});
+  });
+
   it('Should create line elements and point elements for each data item during initialization', function() {
     var chart = window.acquireChart({
       type: 'line',