]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Fix: display stacked bar with multiple x-Axis (#12070)
authorXavier Leune <xavier.leune@gmail.com>
Thu, 5 Jun 2025 15:27:56 +0000 (17:27 +0200)
committerGitHub <noreply@github.com>
Thu, 5 Jun 2025 15:27:56 +0000 (17:27 +0200)
src/controllers/controller.bar.js
test/fixtures/controller.bar/stacking/stacked-and-multiple-axis.js [new file with mode: 0644]
test/fixtures/controller.bar/stacking/stacked-and-multiple-axis.png [new file with mode: 0644]

index 82138f3fb74fac07360128022de78c7ae27e3d96..554497b30533f5881b326d586b6a234d4857e540 100644 (file)
@@ -486,6 +486,27 @@ export default class BarController extends DatasetController {
     return this._getStacks(undefined, index).length;
   }
 
+  _getAxisCount() {
+    return this._getAxis().length;
+  }
+
+  getFirstScaleIdForIndexAxis() {
+    const scales = this.chart.scales;
+    const indexScaleId = this.chart.options.indexAxis;
+    return Object.keys(scales).filter(key => scales[key].axis === indexScaleId).shift();
+  }
+
+  _getAxis() {
+    const axis = {};
+    const firstScaleAxisId = this.getFirstScaleIdForIndexAxis();
+    for (const dataset of this.chart.data.datasets) {
+      axis[valueOrDefault(
+        this.chart.options.indexAxis === 'x' ? dataset.xAxisID : dataset.yAxisID, firstScaleAxisId
+      )] = true;
+    }
+    return Object.keys(axis);
+  }
+
   /**
         * Returns the stack index for the given dataset based on groups and bar visibility.
         * @param {number} [datasetIndex] - The dataset index
@@ -618,13 +639,15 @@ export default class BarController extends DatasetController {
     const skipNull = options.skipNull;
     const maxBarThickness = valueOrDefault(options.maxBarThickness, Infinity);
     let center, size;
+    const axisCount = this._getAxisCount();
     if (ruler.grouped) {
       const stackCount = skipNull ? this._getStackCount(index) : ruler.stackCount;
       const range = options.barThickness === 'flex'
-        ? computeFlexCategoryTraits(index, ruler, options, stackCount)
-        : computeFitCategoryTraits(index, ruler, options, stackCount);
-
-      const stackIndex = this._getStackIndex(this.index, this._cachedMeta.stack, skipNull ? index : undefined);
+        ? computeFlexCategoryTraits(index, ruler, options, stackCount * axisCount)
+        : computeFitCategoryTraits(index, ruler, options, stackCount * axisCount);
+      const axisID = this.chart.options.indexAxis === 'x' ? this.getDataset().xAxisID : this.getDataset().yAxisID;
+      const axisNumber = this._getAxis().indexOf(valueOrDefault(axisID, this.getFirstScaleIdForIndexAxis()));
+      const stackIndex = this._getStackIndex(this.index, this._cachedMeta.stack, skipNull ? index : undefined) + axisNumber;
       center = range.start + (range.chunk * stackIndex) + (range.chunk / 2);
       size = Math.min(maxBarThickness, range.chunk * range.ratio);
     } else {
@@ -633,6 +656,7 @@ export default class BarController extends DatasetController {
       size = Math.min(maxBarThickness, ruler.min * ruler.ratio);
     }
 
+
     return {
       base: center - size / 2,
       head: center + size / 2,
diff --git a/test/fixtures/controller.bar/stacking/stacked-and-multiple-axis.js b/test/fixtures/controller.bar/stacking/stacked-and-multiple-axis.js
new file mode 100644 (file)
index 0000000..ca5490a
--- /dev/null
@@ -0,0 +1,64 @@
+module.exports = {
+  config: {
+    type: 'bar',
+    data: {
+      labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
+      datasets: [
+        {
+          label: 'Dataset 1',
+          data: [100, 90, 100, 50, 99, 87, 34],
+          backgroundColor: 'rgba(255,99,132,0.8)',
+          stack: 'a',
+          xAxisID: 'x'
+        },
+        {
+          label: 'Dataset 2',
+          data: [20, 25, 30, 32, 58, 14, 12],
+          backgroundColor: 'rgba(54,162,235,0.8)',
+          stack: 'b',
+          xAxisID: 'x2'
+        },
+        {
+          label: 'Dataset 3',
+          data: [80, 30, 40, 60, 70, 80, 47],
+          backgroundColor: 'rgba(75,192,192,0.8)',
+          stack: 'a',
+          xAxisID: 'x3'
+        },
+        {
+          label: 'Dataset 4',
+          data: [80, 30, 40, 60, 70, 80, 47],
+          backgroundColor: 'rgba(54,162,235,0.8)',
+          stack: 'a',
+          xAxisID: 'x3'
+        },
+      ]
+    },
+    options: {
+      plugins: false,
+      barThickness: 'flex',
+      scales: {
+        x: {
+          stacked: true,
+          display: false,
+        },
+        x2: {
+          labels: ['January 2024', 'February 2024', 'March 2024', 'April 2024', 'May 2024', 'June 2024', 'July 2024'],
+          stacked: true,
+          display: false,
+        },
+        x3: {
+          labels: ['January 2025', 'February 2025', 'March 2025', 'April 2025', 'May 2025', 'June 2025', 'July 2025'],
+          stacked: true,
+          display: false,
+        },
+        y: {
+          stacked: true,
+          display: false,
+        }
+      }
+    }
+  },
+  options: {
+  }
+};
diff --git a/test/fixtures/controller.bar/stacking/stacked-and-multiple-axis.png b/test/fixtures/controller.bar/stacking/stacked-and-multiple-axis.png
new file mode 100644 (file)
index 0000000..ea57110
Binary files /dev/null and b/test/fixtures/controller.bar/stacking/stacked-and-multiple-axis.png differ