]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Share min sample size with all bars on same scale (#7897)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Fri, 16 Oct 2020 12:04:22 +0000 (15:04 +0300)
committerGitHub <noreply@github.com>
Fri, 16 Oct 2020 12:04:22 +0000 (08:04 -0400)
Share min sample size with all bars on same scale

src/controllers/controller.bar.js
src/core/core.scale.js
test/fixtures/controller.bar/bar-thickness-min-interval-multi.json [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-min-interval-multi.png [new file with mode: 0644]

index 562de63509ca1d55e96ec13e507a4add7e875730..aafe8085624803fc115137b84e4205a09980f5d2 100644 (file)
@@ -1,24 +1,43 @@
 import DatasetController from '../core/core.datasetController';
-import {clipArea, unclipArea} from '../helpers/helpers.canvas';
-import {isArray, isNullOrUndef, valueOrDefault, resolveObjectKey} from '../helpers/helpers.core';
-import {_limitValue, sign} from '../helpers/helpers.math';
+import {
+       clipArea, unclipArea, _arrayUnique, isArray, isNullOrUndef,
+       valueOrDefault, resolveObjectKey, _limitValue, sign
+} from '../helpers';
+
+function getAllScaleValues(scale) {
+       if (!scale._cache.$bar) {
+               const metas = scale.getMatchingVisibleMetas('bar');
+               let values = [];
+
+               for (let i = 0, ilen = metas.length; i < ilen; i++) {
+                       values = values.concat(metas[i].controller.getAllParsedValues(scale));
+               }
+               scale._cache.$bar = _arrayUnique(values.sort((a, b) => a - b));
+       }
+       return scale._cache.$bar;
+}
 
 /**
  * Computes the "optimal" sample size to maintain bars equally sized while preventing overlap.
  * @private
  */
-function computeMinSampleSize(scale, pixels) {
+function computeMinSampleSize(scale) {
+       const values = getAllScaleValues(scale);
        let min = scale._length;
-       let prev, curr, i, ilen;
+       let i, ilen, curr, prev;
+       const updateMinAndPrev = () => {
+               min = Math.min(min, i && Math.abs(curr - prev) || min);
+               prev = curr;
+       };
 
-       for (i = 1, ilen = pixels.length; i < ilen; ++i) {
-               min = Math.min(min, Math.abs(pixels[i] - pixels[i - 1]));
+       for (i = 0, ilen = values.length; i < ilen; ++i) {
+               curr = scale.getPixelForValue(values[i]);
+               updateMinAndPrev();
        }
 
        for (i = 0, ilen = scale.ticks.length; i < ilen; ++i) {
                curr = scale.getPixelForTick(i);
-               min = i > 0 ? Math.min(min, Math.abs(curr - prev)) : min;
-               prev = curr;
+               updateMinAndPrev();
        }
 
        return min;
@@ -365,7 +384,7 @@ export default class BarController extends DatasetController {
                // only if the barThickness option is defined
                // Since a scriptable option may return null or undefined that
                // means the option would have to be of type number
-               const min = computeMinSampleSize(iScale, pixels);
+               const min = computeMinSampleSize(iScale);
 
                return {
                        min,
index 14225354d4e91ba0d2050dbba94351ad58f453f6..82433fc199051fa162fa05c10e1d34a0fa3420ee 100644 (file)
@@ -344,6 +344,7 @@ export default class Scale extends Element {
                this._userMin = undefined;
                this._ticksLength = 0;
                this._borderValue = 0;
+               this._cache = {};
        }
 
        /**
@@ -418,7 +419,9 @@ export default class Scale extends Element {
                return {min, max};
        }
 
-       invalidateCaches() {}
+       invalidateCaches() {
+               this._cache = {};
+       }
 
        /**
         * Get the padding needed for the scale
diff --git a/test/fixtures/controller.bar/bar-thickness-min-interval-multi.json b/test/fixtures/controller.bar/bar-thickness-min-interval-multi.json
new file mode 100644 (file)
index 0000000..6868b8e
--- /dev/null
@@ -0,0 +1,44 @@
+{
+    "config": {
+        "type": "bar",
+        "data": {
+            "datasets": [{
+                "backgroundColor": "#FF6384",
+                "barPercentage": 1,
+                "categoryPercentage": 1,
+                "data": [{"x": "2001", "y": 1}, {"x": "2099", "y": 5}]
+            }, {
+                "backgroundColor": "#8463FF",
+                "barPercentage": 1,
+                "categoryPercentage": 1,
+                "data": [{"x": "2019", "y": 2}, {"x": "2020", "y": 3}]
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "x": {
+                    "type": "time",
+                    "display": false,
+                    "min": "2000",
+                    "max": "2100",
+                    "time": {
+                        "parser": "YYYY"
+                    }
+                },
+                "y": {
+                    "display": false,
+                    "beginAtZero": true
+                }
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/controller.bar/bar-thickness-min-interval-multi.png b/test/fixtures/controller.bar/bar-thickness-min-interval-multi.png
new file mode 100644 (file)
index 0000000..01ad1fa
Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-min-interval-multi.png differ