From c9b38b63dcd4bd198fbf8efca70466e9b9a95243 Mon Sep 17 00:00:00 2001 From: Jukka Kurkela Date: Fri, 16 Oct 2020 15:04:22 +0300 Subject: [PATCH] Share min sample size with all bars on same scale (#7897) Share min sample size with all bars on same scale --- src/controllers/controller.bar.js | 39 ++++++++++++---- src/core/core.scale.js | 5 +- .../bar-thickness-min-interval-multi.json | 44 ++++++++++++++++++ .../bar-thickness-min-interval-multi.png | Bin 0 -> 3898 bytes 4 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 test/fixtures/controller.bar/bar-thickness-min-interval-multi.json create mode 100644 test/fixtures/controller.bar/bar-thickness-min-interval-multi.png 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 0000000000000000000000000000000000000000..01ad1fa1614ae4dbb6aeb7f18dd860f22aeda841 GIT binary patch literal 3898 zc-rk({ZCU@7(VxoOG`oRu+ZW}E)k)d5bFd(Hj&$c&~8kMk}ydl9Wp>e27|!BhW5gQ z2+GP}^J7dbgJd7cpqV7fcgNxsCm$LU>)Z$`5QMRISS+Ko>^y!tRH}JOb5JDRi^29?3kuW3>*Bf5f8^`hx+C(T4rRn8I7k?l6AvYt)+v==q zPBOk)NOz1abNzp=lXcP!B_`RW?D~7vC04SZ>{HdAuKDpc)e$r#39F&UBJ)O9?fpZC zErngnuGXvN=C2>l=n+ABarvkD*WxQ(|CDN+dP{AO?qkir)*I_F=BVuK1U}8M@X>iv z?Zd@mMoLfy^;}Z8dzr@u|G!UB0=ByCwTo^(F)Cx-1A#z^c(otp;25+4nccx?rII1U zqTbJaFds{*IUZsUv4{9&B@TVt`uK`NKUh&*x$KP9Rh0KTV{)R8VFD8(C^ed|&u~2w z+Aps;MwaJCAJ`qsGrv4pyk4(~ZN?O1d?gyY`SjA&bTp}$cI#Q$L{M~2uz+o(8>B3% zQjk1T*xa2PV$@zUa2Y^HNFF0^g{SdX93~9H_}k`=3D`Tslc@lR1bkR3JaVi<-Ncd- zpOd!TJX8J$mIyF*jwSg`-;#X)j@{r?qF{&%UU91;O5JU=Z>AagU54O}945FvcSRuQ zLYM)iRBx+1OG+}$4mhL69R_r2`g?TB>$o52P4QQvaH)QO5+REE%L#y+upnDXN3!Z@ zZ!i?@BSy`J{%t*);# zYkhWRF_mX>oLCJ8q7ytZ;>>oUt)j1Xf-m(R09|1+JKIsWxS|&4-ekA|ZM_!4GgYk)O8Yhl{~Vh(~}&z>5{Y*oCa4OS}HGbU<7Dr_MV6eCa{F@V4@Apj1tJ zV-XzT+%A-=vv)0&Ic>dJy1}^pjv3BSo6vP0`s3?3H4GUHF&Ch+YA7|)yB&1!aW;v* zBa77eoheXTUfGaN(*UOJ9`V}<`jl7M>d{Y5TmGfT0?Pr z%|gRvP=9>y#lrsk^pvlOv`uagV2?_NBJe&nWrCyF=r{T$L^NJxN#hYZ>V6u^{9<1M z?#?a_T>xicWEx;vMUjIjlCi`c0;M($mH^m4Fv)}pH}DpyMJ?3b;$X^fU}O*eDKMq; j2=EAa!2;IDg=`@ab*uQXjof(#{u3j`frE*iGIjNT@bq`K literal 0 Hc-jL100001 -- 2.47.3