From: Jukka Kurkela Date: Fri, 16 Oct 2020 12:04:22 +0000 (+0300) Subject: Share min sample size with all bars on same scale (#7897) X-Git-Tag: v3.0.0-beta.5~46 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c9b38b63dcd4bd198fbf8efca70466e9b9a95243;p=thirdparty%2FChart.js.git Share min sample size with all bars on same scale (#7897) Share min sample size with all bars on same scale --- diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index 562de6350..aafe80856 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -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, diff --git a/src/core/core.scale.js b/src/core/core.scale.js index 14225354d..82433fc19 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -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 index 000000000..6868b8e99 --- /dev/null +++ b/test/fixtures/controller.bar/bar-thickness-min-interval-multi.json @@ -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 index 000000000..01ad1fa16 Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-min-interval-multi.png differ