From 98227b166f20e5599712d449e83c4016f8c9c153 Mon Sep 17 00:00:00 2001 From: Simon Brunel Date: Sun, 26 Nov 2017 14:54:24 +0100 Subject: [PATCH 1/3] Implement equally sized bars When `barThickness: undefined|null` (default), we compute an optimal sample size based on the smallest tick interval reduced to prevent any bar to overlap (bar equally sized). Also added support for a special `barThickness: 'flex'` value (previous default) that globally arranges bars side by side to prevent any gap when percentage options are 1 (variable bar sizes). --- src/controllers/controller.bar.js | 149 +++++++++++++++++++++--------- 1 file changed, 105 insertions(+), 44 deletions(-) diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index b811c6f05b1..3214cf38531 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -95,6 +95,92 @@ defaults._set('horizontalBar', { } }); +/** + * Computes the "optimal" sample size to maintain bars equally sized while preventing overlap. + * @private + */ +function computeMinSampleSize(scale, pixels) { + var min = scale.isHorizontal() ? scale.width : scale.height; + var ticks = scale.getTicks(); + var prev, curr, i, ilen; + + for (i = 0, ilen = pixels.length; i < ilen; ++i) { + min = i > 0 ? Math.min(min, pixels[i] - pixels[i - 1]) : min; + } + + for (i = 0, ilen = ticks.length; i < ilen; ++i) { + curr = scale.getPixelForTick(i); + min = i > 0 ? Math.min(min, curr - prev) : min; + prev = curr; + } + + return min; +} + +/** + * Computes the "ideal" sample range based on the absolute bar thickness or, if undefined or + * null, uses the smallest interval (see computeMinSampleSize) that prevents bar overlapping. + * @private + */ +function computeFitSampleRange(index, ruler, options) { + var thickness = options.barThickness; + var count = ruler.stackCount; + var pixels = ruler.pixels; + var curr = pixels[index]; + var size, ratio; + + if (helpers.isNullOrUndef(thickness)) { + size = ruler.min * options.categoryPercentage; + ratio = options.barPercentage; + } else { + // When bar thickness is enforced, category and bar percentages are ignored. + // Note(SB): we could add support for relative bar thickness (e.g. barThickness: '50%') + // and deprecate barPercentage since this value is ignored when thickness is absolute. + size = thickness * count; + ratio = 1; + } + + return { + chunk: size / count, + ratio: ratio, + start: curr - (size / 2) + }; +} + +/** + * Computes a "dynamic" sample range that globally arranges bars side by side (no + * gap when percentage options are 1), based on the previous and following range. + * @private + */ +function computeFlexSampleRange(index, ruler, options) { + var pixels = ruler.pixels; + var curr = pixels[index]; + var prev = index > 0 ? pixels[index - 1] : null; + var next = index < pixels.length - 1 ? pixels[index + 1] : null; + var percent = options.categoryPercentage; + var start, size; + + if (prev === null) { + // first data: its size is double based on the next point or, + // if it's also the last data, we use the scale end extremity. + prev = curr - (next === null ? ruler.end - curr : next - curr); + } + + if (next === null) { + // last data: its size is also double based on the previous point. + next = curr + curr - prev; + } + + start = curr - ((curr - prev) / 2) * percent; + size = ((next - prev) / 2) * percent; + + return { + chunk: size / ruler.stackCount, + ratio: options.barPercentage, + start: start + }; +} + module.exports = function(Chart) { Chart.controllers.bar = Chart.DatasetController.extend({ @@ -262,17 +348,22 @@ module.exports = function(Chart) { var scale = me.getIndexScale(); var stackCount = me.getStackCount(); var datasetIndex = me.index; - var pixels = []; var isHorizontal = scale.isHorizontal(); var start = isHorizontal ? scale.left : scale.top; var end = start + (isHorizontal ? scale.width : scale.height); - var i, ilen; + var pixels = []; + var i, ilen, min; for (i = 0, ilen = me.getMeta().data.length; i < ilen; ++i) { pixels.push(scale.getPixelForValue(null, i, datasetIndex)); } + min = helpers.isNullOrUndef(scale.options.barThickness) + ? computeMinSampleSize(scale, pixels) + : -1; + return { + min: min, pixels: pixels, start: start, end: end, @@ -332,51 +423,21 @@ module.exports = function(Chart) { calculateBarIndexPixels: function(datasetIndex, index, ruler) { var me = this; var options = ruler.scale.options; - var meta = me.getMeta(); - var stackIndex = me.getStackIndex(datasetIndex, meta.stack); - var pixels = ruler.pixels; - var base = pixels[index]; - var length = pixels.length; - var start = ruler.start; - var end = ruler.end; - var leftSampleSize, rightSampleSize, leftCategorySize, rightCategorySize, fullBarSize, size; - - if (length === 1) { - leftSampleSize = base > start ? base - start : end - base; - rightSampleSize = base < end ? end - base : base - start; - } else { - if (index > 0) { - leftSampleSize = (base - pixels[index - 1]) / 2; - if (index === length - 1) { - rightSampleSize = leftSampleSize; - } - } - if (index < length - 1) { - rightSampleSize = (pixels[index + 1] - base) / 2; - if (index === 0) { - leftSampleSize = rightSampleSize; - } - } - } - - leftCategorySize = leftSampleSize * options.categoryPercentage; - rightCategorySize = rightSampleSize * options.categoryPercentage; - fullBarSize = (leftCategorySize + rightCategorySize) / ruler.stackCount; - size = fullBarSize * options.barPercentage; + var range = options.barThickness === 'flex' + ? computeFlexSampleRange(index, ruler, options) + : computeFitSampleRange(index, ruler, options); - size = Math.min( - helpers.valueOrDefault(options.barThickness, size), - helpers.valueOrDefault(options.maxBarThickness, Infinity)); - - base -= leftCategorySize; - base += fullBarSize * stackIndex; - base += (fullBarSize - size) / 2; + var stackIndex = me.getStackIndex(datasetIndex, me.getMeta().stack); + var center = range.start + (range.chunk * stackIndex) + (range.chunk / 2); + var size = Math.min( + helpers.valueOrDefault(options.maxBarThickness, Infinity), + range.chunk * range.ratio); return { - size: size, - base: base, - head: base + size, - center: base + size / 2 + base: center - size / 2, + head: center + size / 2, + center: center, + size: size }; }, From 867a3693667b4147f309bf150d7343b60bce0e3a Mon Sep 17 00:00:00 2001 From: Simon Brunel Date: Mon, 27 Nov 2017 09:57:09 +0100 Subject: [PATCH 2/3] Code review: minification, loop and naming --- src/controllers/controller.bar.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index 3214cf38531..ff2b56ae5a0 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -104,8 +104,8 @@ function computeMinSampleSize(scale, pixels) { var ticks = scale.getTicks(); var prev, curr, i, ilen; - for (i = 0, ilen = pixels.length; i < ilen; ++i) { - min = i > 0 ? Math.min(min, pixels[i] - pixels[i - 1]) : min; + for (i = 1, ilen = pixels.length; i < ilen; ++i) { + min = Math.min(min, pixels[i] - pixels[i - 1]); } for (i = 0, ilen = ticks.length; i < ilen; ++i) { @@ -118,15 +118,15 @@ function computeMinSampleSize(scale, pixels) { } /** - * Computes the "ideal" sample range based on the absolute bar thickness or, if undefined or - * null, uses the smallest interval (see computeMinSampleSize) that prevents bar overlapping. + * Computes an "ideal" category based on the absolute bar thickness or, if undefined or null, + * uses the smallest interval (see computeMinSampleSize) that prevents bar overlapping. This + * mode currently always generates bars equally sized (until we introduce scriptable options?). * @private */ -function computeFitSampleRange(index, ruler, options) { +function computeFitCategoryTraits(index, ruler, options) { var thickness = options.barThickness; var count = ruler.stackCount; - var pixels = ruler.pixels; - var curr = pixels[index]; + var curr = ruler.pixels[index]; var size, ratio; if (helpers.isNullOrUndef(thickness)) { @@ -148,11 +148,12 @@ function computeFitSampleRange(index, ruler, options) { } /** - * Computes a "dynamic" sample range that globally arranges bars side by side (no - * gap when percentage options are 1), based on the previous and following range. + * Computes an "optimal" category that globally arranges bars side by side (no gap when + * percentage options are 1), based on the previous and following categories. This mode + * generates bars with different widths when data are not evenly spaced. * @private */ -function computeFlexSampleRange(index, ruler, options) { +function computeFlexCategoryTraits(index, ruler, options) { var pixels = ruler.pixels; var curr = pixels[index]; var prev = index > 0 ? pixels[index - 1] : null; @@ -424,8 +425,8 @@ module.exports = function(Chart) { var me = this; var options = ruler.scale.options; var range = options.barThickness === 'flex' - ? computeFlexSampleRange(index, ruler, options) - : computeFitSampleRange(index, ruler, options); + ? computeFlexCategoryTraits(index, ruler, options) + : computeFitCategoryTraits(index, ruler, options); var stackIndex = me.getStackIndex(datasetIndex, me.getMeta().stack); var center = range.start + (range.chunk * stackIndex) + (range.chunk / 2); From eba9e2ba98cf8a34e77b378cefab23fc7128df40 Mon Sep 17 00:00:00 2001 From: Simon Brunel Date: Thu, 30 Nov 2017 21:15:32 +0100 Subject: [PATCH 3/3] Add image based unit tests --- .gitignore | 1 + test/.eslintrc | 1 + .../bar-thickness-absolute.json | 42 +++++++++ .../controller.bar/bar-thickness-absolute.png | Bin 0 -> 5055 bytes .../bar-thickness-flex-offset.json | 42 +++++++++ .../bar-thickness-flex-offset.png | Bin 0 -> 4583 bytes .../controller.bar/bar-thickness-flex.json | 41 +++++++++ .../controller.bar/bar-thickness-flex.png | Bin 0 -> 5095 bytes .../controller.bar/bar-thickness-max.json | 41 +++++++++ .../controller.bar/bar-thickness-max.png | Bin 0 -> 4421 bytes .../bar-thickness-min-interval.json | 40 +++++++++ .../bar-thickness-min-interval.png | Bin 0 -> 5180 bytes .../bar-thickness-multiple.json | 46 ++++++++++ .../controller.bar/bar-thickness-multiple.png | Bin 0 -> 5847 bytes .../bar-thickness-no-overlap.json | 46 ++++++++++ .../bar-thickness-no-overlap.png | Bin 0 -> 4211 bytes .../controller.bar/bar-thickness-offset.json | 47 ++++++++++ .../controller.bar/bar-thickness-offset.png | Bin 0 -> 6577 bytes .../bar-thickness-single-xy.json | 40 +++++++++ .../bar-thickness-single-xy.png | Bin 0 -> 4514 bytes .../controller.bar/bar-thickness-single.json | 43 +++++++++ .../controller.bar/bar-thickness-single.png | Bin 0 -> 4374 bytes .../controller.bar/bar-thickness-stacked.json | 48 ++++++++++ .../controller.bar/bar-thickness-stacked.png | Bin 0 -> 5586 bytes test/jasmine.utils.js | 3 - test/specs/controller.bar.tests.js | 82 +----------------- 26 files changed, 480 insertions(+), 83 deletions(-) create mode 100644 test/fixtures/controller.bar/bar-thickness-absolute.json create mode 100644 test/fixtures/controller.bar/bar-thickness-absolute.png create mode 100644 test/fixtures/controller.bar/bar-thickness-flex-offset.json create mode 100644 test/fixtures/controller.bar/bar-thickness-flex-offset.png create mode 100644 test/fixtures/controller.bar/bar-thickness-flex.json create mode 100644 test/fixtures/controller.bar/bar-thickness-flex.png create mode 100644 test/fixtures/controller.bar/bar-thickness-max.json create mode 100644 test/fixtures/controller.bar/bar-thickness-max.png create mode 100644 test/fixtures/controller.bar/bar-thickness-min-interval.json create mode 100644 test/fixtures/controller.bar/bar-thickness-min-interval.png create mode 100644 test/fixtures/controller.bar/bar-thickness-multiple.json create mode 100644 test/fixtures/controller.bar/bar-thickness-multiple.png create mode 100644 test/fixtures/controller.bar/bar-thickness-no-overlap.json create mode 100644 test/fixtures/controller.bar/bar-thickness-no-overlap.png create mode 100644 test/fixtures/controller.bar/bar-thickness-offset.json create mode 100644 test/fixtures/controller.bar/bar-thickness-offset.png create mode 100644 test/fixtures/controller.bar/bar-thickness-single-xy.json create mode 100644 test/fixtures/controller.bar/bar-thickness-single-xy.png create mode 100644 test/fixtures/controller.bar/bar-thickness-single.json create mode 100644 test/fixtures/controller.bar/bar-thickness-single.png create mode 100644 test/fixtures/controller.bar/bar-thickness-stacked.json create mode 100644 test/fixtures/controller.bar/bar-thickness-stacked.png diff --git a/.gitignore b/.gitignore index 53ce8fedb1c..cfb878a6dee 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ bower.json *.log *.swp +*.stackdump diff --git a/test/.eslintrc b/test/.eslintrc index 8e8f899bffd..9d98c452878 100644 --- a/test/.eslintrc +++ b/test/.eslintrc @@ -11,3 +11,4 @@ globals: rules: # Best Practices complexity: 0 + max-statements: 0 diff --git a/test/fixtures/controller.bar/bar-thickness-absolute.json b/test/fixtures/controller.bar/bar-thickness-absolute.json new file mode 100644 index 00000000000..599b090d6d1 --- /dev/null +++ b/test/fixtures/controller.bar/bar-thickness-absolute.json @@ -0,0 +1,42 @@ +{ + "config": { + "type": "bar", + "data": { + "labels": ["2017", "2018", "2019", "2024", "2025"], + "datasets": [{ + "backgroundColor": "rgba(255, 99, 132, 0.5)", + "data": [1, null, 3, 4, 5] + }] + }, + "options": { + "responsive": false, + "legend": false, + "title": false, + "scales": { + "xAxes": [{ + "type": "time", + "offset": true, + "display": false, + "barPercentage": 1, + "categoryPercentage": 1, + "barThickness": 128, + "ticks": { + "source": "labels" + } + }], + "yAxes": [{ + "display": false, + "ticks": { + "beginAtZero": true + } + }] + } + } + }, + "options": { + "canvas": { + "height": 256, + "width": 512 + } + } +} diff --git a/test/fixtures/controller.bar/bar-thickness-absolute.png b/test/fixtures/controller.bar/bar-thickness-absolute.png new file mode 100644 index 0000000000000000000000000000000000000000..40172b39241f2a6e13d201f7a47509137acc468e GIT binary patch literal 5055 zcmeHLe^gU-8-MQQA{Pi8>=>pT*g%F!uR}A%6F+XTcSFf(?|F;fw^xU!Q)HUUOg4nU zm$D{epsxp)S!~)lQc$2$NV3L`l|UHlgi1Na29$^}_XBYZ*w%N}@f^!PJN?uCxaZ#I zJkR&@e7?_lew|yfK`e?0TMz~S5o>Y;{{kTKCjs;v{QCMpPXPe?tu=zj{w?2RHD*-3 zTrh9XV6On}+1nL+73+n`aTzjy^9*HdyPx`SC;)5HD z={wm`ezzq=nl^~C*y)FEyRw8cx}ZCb2nj^mfJjRx!*4U0A`f7(^Wjxd7?;t<1l$IK z{AZ?=d|r9Hx7!h;)?HWjxRhC6m@;R*C0j#QmX=PBSV!G$#p@Hm#k=m};$)TaQXTD8 zYN@)vcDuU&0n;O;ritD&lx4w_yMz5jvxKB9Pqj9>l%e{`<&z0GVJ%4%tWs|v6k?IHDIupoPKSQA8i*#(-Pa^e7MC;b5e5=ToBsk z+;tQy7y6Ya*CP0s=T`rl^`P4u{TOZ!hCQb;q`I)e_V`HQj8q-tx5fc}Co~x~!wOx^~4+RjEEF z@in$!H4a;n5921q zNS3G_<8wgvb&*aYgdWw86{~oV9BGSdV58ybZHE+Bxkf%@ehkF11Ma7jVWfM!aUmPE z4VAd~iC`1TZ%7#EdEeaCk_^e=;{#*SsFC_0)J zfep#tj8B5R9LEYN2kI)WFRP439j_?Hq)8x6k{whhLQJSL*1&<0&e6@!MkD1hMK7NR z(sPCH$0tBvmy_aiA(*pxl?df8$4U+Tqy)WgxXgsoYw1H-}q<-`n&Fs6`eU*h&JI;=)6F~KLi(@mTSyp2aQyh9G_ybxW&e`a$ zW}%e2XI(4F4KZs9x#WSLJ*T!%mgn{?^{UyZGNgYpo&2swRI-p{iM-80p-f(!<7JwO zbvqgIQci$wH0kLq--#bN*aT<*&vxRGGww zm5bU~M5i-OEriSAmL{lQz(D;_CqEl6JIdr}G-&tCV(LXJ7D#I+^xyBo@a?!j=*A1`Q*2oMZJ@Ykdc zoVE3Y?(+Zf QFFJrV{}c-vAJ2dN7yOH(lK=n! literal 0 HcmV?d00001 diff --git a/test/fixtures/controller.bar/bar-thickness-flex-offset.json b/test/fixtures/controller.bar/bar-thickness-flex-offset.json new file mode 100644 index 00000000000..1776b07be16 --- /dev/null +++ b/test/fixtures/controller.bar/bar-thickness-flex-offset.json @@ -0,0 +1,42 @@ +{ + "config": { + "type": "bar", + "data": { + "labels": ["2017", "2018", "2020", "2024", "2038"], + "datasets": [{ + "backgroundColor": "#FF6384", + "data": [1, null, 3, 4, 5] + }] + }, + "options": { + "responsive": false, + "legend": false, + "title": false, + "scales": { + "xAxes": [{ + "type": "time", + "offset": true, + "display": false, + "barPercentage": 1, + "categoryPercentage": 1, + "barThickness": "flex", + "ticks": { + "source": "labels" + } + }], + "yAxes": [{ + "display": false, + "ticks": { + "beginAtZero": true + } + }] + } + } + }, + "options": { + "canvas": { + "height": 256, + "width": 512 + } + } +} diff --git a/test/fixtures/controller.bar/bar-thickness-flex-offset.png b/test/fixtures/controller.bar/bar-thickness-flex-offset.png new file mode 100644 index 0000000000000000000000000000000000000000..e20cc4eb450c8f90b94da145252619ba60cec024 GIT binary patch literal 4583 zcmeHK>r)d~6hC{j;0A-)Xtj!nOAwV7LA2JOJQfI`#p3(XN`)#dK1oEyAWC*)%R_C{ zX~$@dQroe9utht>X2%I@XKM#PQNCD%Izl(dEc>tQKnfjy!re&S2G0tx`jY@xf;Lg5h ziy|8?{d8f}X(nc^n5?a6xNyVo^736ZpG?nDSG(R_d3l|&Ew{9+tJ|)gaQ?@xVrRYX z%ouk`x0*1VE0Gu~`|h1^w6xq8I6>-Bww_45o=mf*Xo_+zo0m`~^(q;mdwMm9HVq5W zDSzx__mAV?_o1<@*ugMD#}ZFCU6N0TeE&_^tr@Q6pfp$KCsytk;CTh**+M(@JlL=7 zTdFZx1u$7F`-8*`G-bQ7N=5o@0=RgVmj@6ct>C{%;bCLe(j8I?+6&c==H*E=Eq$;c z$Rc&4(5>30AbFu2IG0~N#02v^1jFsw+{9!ac9k3b$w1Vx_)X=EDvC0y^6D*81V%W2 zWx*H{jk}gvuG=_cAes&e`IeXCQM-72uZn00;k3WZqVpXG!KM0-1oI*u+JG=yXYpWC zGaH%bLj>!Z42@|94{`dt3MQ*mfYZC)N?}ch5!J&-47?nP3B5Dx%n(t5St~e?l1@WG zqjB;%q5w-y%Ko$!VX*%8a51a%Lx=+2w(8|@+?6r$ufcRx5)WDDzZ%Nam7zs-cx4iY z!0Pn}D}?$1(nub}-AV?!C~**FCe7>DMG!SoqpW-@h)pckbM7jJTpPl|waHHd8T-cq z=ypbI)*1mFL2jZbF%&gXdu{|1iOK_qwF*)UdXBMs1IRIsgUlmW_A+%Jp=V`UwndtP zk*_gT6VZ*@T}SRtX7spHzH+k0P$Vq7SIrqmV1XyS z7MLU#p-@!%10|k98+kGJGU-9+Xpr!596KCwNYm>Sq8}kS4VICt4&l_5p2|*=U%{v% z-iRG6+HhBN!-EX=v_Ga0xO)-j3PFqUpKbLQF&9>|ZY=2w0RvEU!dMRK2GG;!7fQad z<|q?4hJz686N-*PLT9BN4Q1kHW8JPbBR7YkjmWQCD+US{-28L>qaAoWXs&;#HP$MHLyI{m%-R^Of%n||?qd^a6pD}wchMGUe$I$ytn>iO= zJ%wW;Un(6Za*O9y_KQ2rY9cdNOTsdE$h|qTEer>n-IEQ|qt4nGp{lrP1723G1=Puo zFN-VS!C6OKIu8%Wzv@%);qd?BgS?P3)?zn#nJtFOZM|1I@rD@ucxj1345p|(^Ye{1 Z$qf1fHLEYRwyyyEW~OH9tCDjpe*@UW)UW^m literal 0 HcmV?d00001 diff --git a/test/fixtures/controller.bar/bar-thickness-flex.json b/test/fixtures/controller.bar/bar-thickness-flex.json new file mode 100644 index 00000000000..0bef9db1828 --- /dev/null +++ b/test/fixtures/controller.bar/bar-thickness-flex.json @@ -0,0 +1,41 @@ +{ + "config": { + "type": "bar", + "data": { + "labels": ["2017", "2018", "2020", "2024", "2038"], + "datasets": [{ + "backgroundColor": "#FF6384", + "data": [1, null, 3, 4, 5] + }] + }, + "options": { + "responsive": false, + "legend": false, + "title": false, + "scales": { + "xAxes": [{ + "type": "time", + "display": false, + "barPercentage": 1, + "categoryPercentage": 1, + "barThickness": "flex", + "ticks": { + "source": "labels" + } + }], + "yAxes": [{ + "display": false, + "ticks": { + "beginAtZero": true + } + }] + } + } + }, + "options": { + "canvas": { + "height": 256, + "width": 512 + } + } +} diff --git a/test/fixtures/controller.bar/bar-thickness-flex.png b/test/fixtures/controller.bar/bar-thickness-flex.png new file mode 100644 index 0000000000000000000000000000000000000000..791a29d25d380f64f8c33fc3a928cebc531348cb GIT binary patch literal 5095 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 literal 0 HcmV?d00001 diff --git a/test/fixtures/controller.bar/bar-thickness-min-interval.json b/test/fixtures/controller.bar/bar-thickness-min-interval.json new file mode 100644 index 00000000000..e5861685cd4 --- /dev/null +++ b/test/fixtures/controller.bar/bar-thickness-min-interval.json @@ -0,0 +1,40 @@ +{ + "config": { + "type": "bar", + "data": { + "labels": ["2016", "2018", "2020", "2024", "2030"], + "datasets": [{ + "backgroundColor": "#FF6384", + "data": [1, null, 3, 4, 5] + }] + }, + "options": { + "responsive": false, + "legend": false, + "title": false, + "scales": { + "xAxes": [{ + "type": "time", + "display": false, + "barPercentage": 1, + "categoryPercentage": 1, + "ticks": { + "source": "labels" + } + }], + "yAxes": [{ + "display": false, + "ticks": { + "beginAtZero": true + } + }] + } + } + }, + "options": { + "canvas": { + "height": 256, + "width": 512 + } + } +} diff --git a/test/fixtures/controller.bar/bar-thickness-min-interval.png b/test/fixtures/controller.bar/bar-thickness-min-interval.png new file mode 100644 index 0000000000000000000000000000000000000000..ae01a9b945c4ef691bd0a861cdce518f6c23e872 GIT binary patch literal 5180 zcmeHLT}V@57=FKRCpl-fJT8Mu%42Q1ewDh=Na{G1wlp0gSW(ML`nhSNprqzHvmYzS zriLYy*bf*5DNz}Px{At}7}mvtEuAS=gtgR`ZEoxANcKZFK{vsbj~rCW)3z zeO&CWIR*(gX|d zW^_9}bzk71gxr=Z0C&+eq?ob{jIb_h5@E|o9>*CE zad4-1!F~x(N75xK24@h0ZR&~*vvIZzggkV|xo}z1#W1jI^hEb~7qg`# zS6(zQUNr(Ce1l&j-<`<1 zuW&%RFvHX?M5yVoi=tEKGk}|c)FfoHurPifCMx&=wJic%^;AwncKdm-T*8wJjuZ4-Urd95b&9nFGPT zq@It%PWvR*C(HK&GywdxOA78D7HK1;By2o)6&6%Z8= z6%Z8=6%ZBpYXwY|$m8uzYFmGB^qv2G!^*(>5rcV6TOvGn{OmhyXJ$Z;$$vZOx%9>1 zXlpV1`r;~r1BKqLm?=&E&5Mk@*a$gFlziMglaCDwJ~m8b38Xu$|AVE$^(4hz?hio> z?`ux;zGlffjEg9Wo1=iLDp2vZNkx4R8*<3ffI^9MyaCcpY*+y&te{zq>ys(2K3r3X zDjJB1M^>J3vmDaHE~;9|K#dhtYRt@|xCaU-`=vR8&6mRw9;lqKTjRYcKw1st>IwTs zu+ehRYQ=^{g}*0faU}lrp&J<*@&%qaQcIhcB6>xO@E37sPv$~s?}p~r1>W`$e=7*u LtlZ4&>Y}o5GpccS literal 0 HcmV?d00001 diff --git a/test/fixtures/controller.bar/bar-thickness-multiple.json b/test/fixtures/controller.bar/bar-thickness-multiple.json new file mode 100644 index 00000000000..fc39849ae86 --- /dev/null +++ b/test/fixtures/controller.bar/bar-thickness-multiple.json @@ -0,0 +1,46 @@ +{ + "config": { + "type": "bar", + "data": { + "labels": ["2016", "2018", "2020", "2024", "2030"], + "datasets": [{ + "backgroundColor": "#FF6384", + "data": [1, null, 3, 4, 5] + }, { + "backgroundColor": "#36A2EB", + "data": [5, 4, 3, null, 1] + }, { + "backgroundColor": "#FFCE56", + "data": [3, 5, 2, null, 4] + }] + }, + "options": { + "responsive": false, + "legend": false, + "title": false, + "scales": { + "xAxes": [{ + "type": "time", + "display": false, + "barPercentage": 1, + "categoryPercentage": 1, + "ticks": { + "source": "labels" + } + }], + "yAxes": [{ + "display": false, + "ticks": { + "beginAtZero": true + } + }] + } + } + }, + "options": { + "canvas": { + "height": 256, + "width": 512 + } + } +} diff --git a/test/fixtures/controller.bar/bar-thickness-multiple.png b/test/fixtures/controller.bar/bar-thickness-multiple.png new file mode 100644 index 0000000000000000000000000000000000000000..d38405292c3b496ae1414813c6bfd120f83ffc8a GIT binary patch literal 5847 zcmeHLYfuwc6u!GIbupj;96(VMQK3}?v10)-B!wuTLZZ{53egGG+N@1)))r}!getwXq`3F2?@NVfYG`+AUd@CT zQ}={tYNsfw>H<$XNz=4>m8%(8tVpv<)S%*L0R+WDJrc&d%1zHk`unv<^-YGrIq{m& z!&1;;T;Me-9J?x!j~p<#nzVKnGS7XCVp!5O3n$_jmjs=bsPZh?R@f3kiSk4-oT{Ut zXw-2Uj#M<9m%2b~{|q}!mO7EYNazx&Vm_L(k;UD7upOcL&s)MGWX>?VD1c@%A?iSo zH|3TVf@1CgED-r<;p0lR6H(Cc@q8z3sUYu61aM1?Ee|F@2A2ggxhg*w&`chjaD_0p zAxuQek75^4$~aPoQ|YVNEMOJQBu~vE{wg+XfG2z6MhCmAo3kXAgtaH*X9(*+rvrCo zPU8xkU^iO9HtjaB&8u*88#8I2#-tq*ruFUfwNucLjKtR>Z_FOBh$) zx@eSEbPZp#kcGW?efLaFVxMcE+8 zs>bu9OyR^K`QA!q`&uKe+;+W0a*F^R;jQENRKmvuP8K-bOKo>_r-Ll949&xFB6#*n z;Np|HCX0d-J+2kgnlA{Tzsx?haj?idh`b7(&azP`WVU4*vgX)Rb?<5Y)_oTJAF+Xrf8$UEEc%#kNT1e#U zFNwl4CM#AZ?cCjsp z$UCqog9evNf!GS+uCOFJ8`w+fz}Y1L>qJrd;y?|4&)Mji1@e>?_-UzGta7h$Zpn_be%ngfX*^CHtWfIs+x zQQ<}eITlMH!h=EU29)mEX-VWXQZsH7APBc$l`RE(mLSI*Er}o)tcF1=bI?qPc^Lk8 zLXiDAL#Zf99~l*m^(m^Vn@SCae6jph{|uhK*J)HV*__JUSKRVyPZ(&8M9+O?3v!Qx zoD)_yZz&6Wfl*UMOEaAk4csp?%H6>G6&6sn1|sL62ksp!JXhRpXB~FNjyW)ces-0_hGzGg|UKf+WosGaN;5NpL0=ss9!+m7tL_b}MbGt5cIOYLh%~teu6Zs7^Y_Pm z*n%W%sJ}kA9hxn@d}!y0)L-)CWG9CVd4D^*2`3ujpz}+!c3-y?*!xv~%e*4{1yPU6 X8|KBe-5M4ZPf}8qETL*q0C;`9?wd!Y{!UnQH*F?uo$uQO^Qi|!V|hsc`MT&kWG9uouR1^Iv*PL#PKejwmF|U(mX5EM zqNdC}uL_KVn!CAr9)e;xL2A9Q(Nc|A6LBwB!!zt>$Eb|AWx82I*IejU(cUjWcg)ZX zK~gl3IbxX7ruNG7uiIM&!h5a6ZM^WH8j`Z$Vabha!xTbClN3H&!&EXFVr-Qw-#WnI?|bDvr* z6w0Ujd8Ra;kK$_@OzIzSKUMNK>GOfa5VSh;uDpYz%s$GSN`+i3l2r&8Upt(xednSn zpcNAGw&;ha_*69wx<4O&EVv9u46dP&t!8HeoR%rW5F}{q*Fa}d8-Zc8>$V^P1xBtu z=3_Vx_EQ-ikoqG>LvaL62Y&;Z7}8jNP3T1_9cWKd@evJ@=XY?=0VEKdrk`Ok9HkSH z97_TJJXfcKH0@@AlGC6rYoQh=v}lGc?(a>4njU-GZEH}^mMuUO8?YJ}+;Hmq#RSPh z)xAuD`IHr36uS;45p)>G>CEt=Ysnlny=|c5)zkJx1$xpZ~YJ=m$ns8ewUxG`xQxtk76HJM$2#97|;}Bd$uHpfUWIn^WekYxzK*DAq@%oK>WBv#N+rVZxe>RYv zwn*{NW&+stgZPIdF0eb%)M2PhJ*!O0QuwXT)`b1HBq=xsE>%hme_YP$lju~^X+xLU zn6I9DR5};dukX=C1V8ybhbwe4e!13OMqgV>_vA$sy6?)7cLWMVGaJqA8(k)o8L_2B ziB`Lc@}92T8R%OUNmqpk%BX*?_f}kkXFP*}TNDDNl3M4+YQ^kkRfn}A@c&m;aN-5J zRFm>bkFlAfTsUSruXIG!7xOzRDjUM5w9R8HAL}HA;xj8Iag^zTa(D{?hK%;C7%U$f h)L};Qz4VmX;hTBc-E)lg0{oc(5@Hgg+Ye@({Rii=3_t(? literal 0 HcmV?d00001 diff --git a/test/fixtures/controller.bar/bar-thickness-offset.json b/test/fixtures/controller.bar/bar-thickness-offset.json new file mode 100644 index 00000000000..b31eb739d2b --- /dev/null +++ b/test/fixtures/controller.bar/bar-thickness-offset.json @@ -0,0 +1,47 @@ +{ + "config": { + "type": "bar", + "data": { + "labels": ["2016", "2018", "2020", "2024", "2030"], + "datasets": [{ + "backgroundColor": "#FF6384", + "data": [1, null, 3, 4, 5] + }, { + "backgroundColor": "#36A2EB", + "data": [5, 4, 3, null, 1] + }, { + "backgroundColor": "#FFCE56", + "data": [3, 5, 2, null, 4] + }] + }, + "options": { + "responsive": false, + "legend": false, + "title": false, + "scales": { + "xAxes": [{ + "type": "time", + "offset": true, + "display": false, + "barPercentage": 1, + "categoryPercentage": 1, + "ticks": { + "source": "labels" + } + }], + "yAxes": [{ + "display": false, + "ticks": { + "beginAtZero": true + } + }] + } + } + }, + "options": { + "canvas": { + "height": 256, + "width": 512 + } + } +} diff --git a/test/fixtures/controller.bar/bar-thickness-offset.png b/test/fixtures/controller.bar/bar-thickness-offset.png new file mode 100644 index 0000000000000000000000000000000000000000..8dcecac88a409dff7867684f0987662f1cc4f46e GIT binary patch literal 6577 zcmeI1dr(tX9>>qU1PCCT2rdYLP1YAwQ1A(uLZWCXB4|sisJwiEyU1H4kPw2dB4Y(B zAdN(VrE80{pdvvGk|-h~V0<P+BsAGF;?NZln|8v(uX9xG*@5C3hE3~{-J6a3a+92_J`hGf# z*|}EDqvA<5x~XMNw^ke;J~Cd^TwKr9Pz1{30{S7nKz1scEzii3Ue=t?%ECbKTey2V zVO^tGWyCcSSwusRYy5n!VAJ<5^Yx*jfc4VQe+(u}XPpN{Ml_mXZ0~yDH5d5gJ2bRk zHD4#*+y*AcR?z0bs09#&&6I1d0Po<_!29;@2nPQe1H>#D>avDw)pOulRQfUq?uFq* zW`?UPn(<^6n&H&mfs-^# zL(jg16E|O@2nuca()x>K@BRknpFP}=g zLIj3olwgSJG_x6&47>0+8aqbH+gpVdg}b14b%uQN^gw|Xw!IFZuXvocMv=E9)h_x_ z=$$FnWU$T+2otoo3TNMLHB9y2o^2&gG=UR@Y9X3&sbjc=pJpY&hv>@&m6QlobFA)1 z9vs+Ghcs)RSKC^XM{}03T!8S7Pl6|@4%}ELdK>_56K8D*{H)b3Sg?Xwbe4he1Jm?J z0R8Y^<1YoUZ`eMBUFB}xb_kIS?{-00hCKuHK8_)SyZdc6!w9-a?b`vW7PfS2nFLEF z{Ljl__%FaCfj8s8%ic4Q9L%C>q$S)VIM6gS(=QjK85>I2$^?@IsE~ESq1L5v!)O*)fitVLD+)`m?FUb zm_d#m}9b--exEpVikI*fd)V33#&Lc6MfZI86^41(R3Pl#svzh^VwKbWs7_9V# zuvE9P{}={L(5!sqj0M5^o_?6{XdZyhf%{0r$pf`s1dy*OueK)FeuNMfIFAUI7jaa!}IN}1L}K+@gk zc-FYj9@^?rLswtD$c+t^EQ4Xm#LRIlB8w1AAkSkG%<>3oHj1>nf6f5^`m#8fuOsx|NhUb2S{7!XxV@MZQuUgqy)Yc6Rhkh zaWEVE92ITaD!TsF-MGOcG~+8d+syBaE3U$L2}B=fBKl??iDqo|3oaaVRXn)Vm@#`L zI6E*`YWkXcB)>;#C@(uS_`!;5?@GtR@VJ}3Yfz#E{%$}(dp(qHdMp@z{{)4oKa;*N zUzTHDp%Uv;iK4@Sc~j3z1T8}1A3l6aiz>LmRpe2|mO|L|9a*w~)~2CZ<-t+=;)H*S zwH-B*081*8O!ktB zZDP_Wj?sreB0fs{E3GwxhmvAUa}zBJ%A!#%qWb^LwkTEujvN6PZZ-(xhmWecmG^2T zbmk-a%xro>zKP=}s*H@2s`pSwGp6ns7v{>3muivi5LQ3c7t0 z8N_<>urPrVhFCG34WU!z_-oG;VC9~>jaFI;s=lMN{bXYa+%2S%E)2eSMeDKsmdZxBxZRYclMZED0)lfrdm0Wc` zg@C*O@~6T7q90hf2|AN!$LQ-F|Ce7JZNY-7ps9{GQu2tr42drlgYVK`A0>|JEQ zI{#Opt)DIb#f~7Z;n==uNAfI=(!$#}p-j7=b>wpwrwT6fU$b#qv5qPKJC1aH_G=MK fy92n%3ZcHs(Z24L4=Kp67!bZGYGdPu#H0TJN7H47 literal 0 HcmV?d00001 diff --git a/test/fixtures/controller.bar/bar-thickness-single-xy.json b/test/fixtures/controller.bar/bar-thickness-single-xy.json new file mode 100644 index 00000000000..76caa37fa1a --- /dev/null +++ b/test/fixtures/controller.bar/bar-thickness-single-xy.json @@ -0,0 +1,40 @@ +{ + "config": { + "type": "bar", + "data": { + "labels": ["2016", "2018", "2020", "2024", "2030"], + "datasets": [{ + "backgroundColor": "#FF6384", + "data": [{"x": "2022", "y": 42}] + }] + }, + "options": { + "responsive": false, + "legend": false, + "title": false, + "scales": { + "xAxes": [{ + "type": "time", + "display": false, + "barPercentage": 1, + "categoryPercentage": 1, + "ticks": { + "source": "labels" + } + }], + "yAxes": [{ + "display": false, + "ticks": { + "beginAtZero": true + } + }] + } + } + }, + "options": { + "canvas": { + "height": 256, + "width": 512 + } + } +} diff --git a/test/fixtures/controller.bar/bar-thickness-single-xy.png b/test/fixtures/controller.bar/bar-thickness-single-xy.png new file mode 100644 index 0000000000000000000000000000000000000000..26171e531a2b87dd1fcfb8014cb437a531fbe1c4 GIT binary patch literal 4514 zcmeI0`%e^C6vxlK49iGanFX=RW0_r~+7*z{ip63aV0jxvx*%;qC)NfVP$FmwvC6EZ z3L>~z*GD3SL`gw;Y}1w$f^@ID?9<=Qb;#mn#} zAZ3ahH+uH;xrIhzV^=Lxloe`-T! zy#*+GnXSh>PVz{v&^XpsJpbqNsj-oq$+8qy}0O1*@dHpJ+~Iv^*{8~9>) zg5-iJALB|Sw{Iw~lai(FEYq~J?S zwMo}u8p%VpP+ExO56(CO$q^XmSmBRJPh%n$=IiWJtZ)rTRnuurByzlt>yEB~-EK_N z(UOB!HP-3ZR{cIYfaJyI1m+fsp*zjpp=iSVcjZK=a*;ghZ@$fzF=Gb=@L#%-4MUOD zwA=J>6B{r`W1o>0j50@34qxFqkb#y!Z6vDhO193l3icxTo04j)KaxjVVw0^Q)@bHG z#XR}iE84AZ1P79nrZ{5^p0Fd!*h}spxxt*yjAH)ZB~8UpHR;mG(v_tvOIN;i)GNYo^I(l4m zT{D(7UJz`k#Z_D@Zp`}?Dq**vLdbO54PlvV3OW$1mnwAsL-x&&P4=lD-n8j?-{*Os z-~YL!$EaSmBt-CnfDjU*RAlB5LgOn%0w>|)d(-7Lga~_-nXl$mti0>G@Wtw%LwL@} zJvX}rBN->}Ww48Os16UNEAkUgFP9$us{xnMu?+KeSMNK{pm~X)^seCb8fBI?V@;IWm954q8B|@o{@U}lr-?yLG zV()y+3lz$NWF-28+#qJVrV-OPtm*^usPJUCMJ#~{nIFtFvYl8^CIg5oq#cS z@!?b;?tIyi8KR?k*5~h58 z-a>c9Y@%>S5!kfnrT5x=1>p%{bdDQK;PV6v<14DR&LbTGN21`P6t{|eSe_dWpfOV= zOrMFRH_Dp29RkL9X%?<+3zm`FL36M+&&2*L8V~Mv&Ei7UMkDG}L|yN`DCHOb(36M# z35dF8@-Hj1skLEexI8i9#45+W4LQDo7@H(X(+tgKSY|l`&XMq<4PpN0#w3u!J%UgTD|In&k*KqpwzW-YeLK&EFPq8QXteC4Oei>7^-4T zT9T5geJ_QplMY1PPaXd?m$%68|D{R zGFKsvvzi6O@%0V>bxDyB(@}b%+cj@$DA{)lGZE${piC>_)`XZ!1`lSuY(uCW4n$oM zYbEE7TIy`%;wdv%C;bq2gmn$Zk+O^kp@fmV!BC2&?opMmARN8Kc5r~}Fl!-qSzCX^ zBlG~tAjBztjR8b`iUvT-L`aBG^b12<{9y;#b!|GTojC)PmS%2EhzY57T??I&gHTs% z5cRn*HMvpHxip8A{;uNc`fHTRgMB3^!apvanVbG`;U5?Ne;3dG&GL^6|G4=7#)b3Y9D-L8dmEzmI>>Vurr}-0 d)*jl+zg+8GC)Z!M<9!EFE?$=TO-Au2{{nTa>rMaw literal 0 HcmV?d00001 diff --git a/test/fixtures/controller.bar/bar-thickness-stacked.json b/test/fixtures/controller.bar/bar-thickness-stacked.json new file mode 100644 index 00000000000..aa2d825533f --- /dev/null +++ b/test/fixtures/controller.bar/bar-thickness-stacked.json @@ -0,0 +1,48 @@ +{ + "config": { + "type": "bar", + "data": { + "labels": ["2016", "2018", "2020", "2024", "2030"], + "datasets": [{ + "backgroundColor": "#FF6384", + "data": [1, null, 3, 4, 5] + }, { + "backgroundColor": "#36A2EB", + "data": [5, 4, 3, null, 1] + }, { + "backgroundColor": "#FFCE56", + "data": [3, 5, 2, null, 4] + }] + }, + "options": { + "responsive": false, + "legend": false, + "title": false, + "scales": { + "xAxes": [{ + "type": "time", + "stacked": true, + "display": false, + "barPercentage": 1, + "categoryPercentage": 1, + "ticks": { + "source": "labels" + } + }], + "yAxes": [{ + "display": false, + "stacked": true, + "ticks": { + "beginAtZero": true + } + }] + } + } + }, + "options": { + "canvas": { + "height": 256, + "width": 512 + } + } +} diff --git a/test/fixtures/controller.bar/bar-thickness-stacked.png b/test/fixtures/controller.bar/bar-thickness-stacked.png new file mode 100644 index 0000000000000000000000000000000000000000..696829ee39b400f7bd77dbc1b930784d3cf42542 GIT binary patch literal 5586 zcmeI0dr(tn7QoNFbD=k&B?Jq!IBS4_Aj(5$&~7QYAYcMnL+g%itJ`2@mSvYUUF{6C zJaWTQ9#u3vEViIQZO83)6_qNW0>Lh8k@`s0;v)oHr6`mTKn)O*>`APYcK_W!c02ha zljJ++e&5MC=lh*=QkJ@Q&3v~P+yG#{Sd{Q80Er(7pk48;Q*|i=;JFXQ330#9d1K^O z$7he;i90{Gy=q?QIq&tUM{bD&CKfbiX_;le(_VO;^IpK`Sy9yH{`lX{d*~sd55DA* z-B`NwN}{_qldPcs?(KO`K*cNftSmk?FqnUOh3t~f{LzRdX0UE_*j!t(axgaA$L7gr zSRhFGXBvyl^0>RkY_8FNv$AEpbM&aL*6WFIgB#6;b$rF);#bWUE*Ey+@!qGzrzm<; zC?AeeD;7I8*&W9~O!3CIT~Wa0zx4?V&AhMb9C|UX1Yz{us(l^>xXB)p>`#u|?$9&( zQj}&(b7IEN@vyDS!O%W-V0W*#p|`PnzqEZh&uTDw=5P@47AYREZNB7Jx4G~|438Z}Z| zlhK>Q_^cSR4s|C!ap^9M%DJU*suFG_k@db9y0=6a`ri}B_E4H=9&~9o{R>| z9bv(}n=e`U@w1n7E_ z&;JlAcCY`KFFbW$)9!ix(^B!vAriiuo~ zgxJdheT_^DbP%Gjf{R94ruXx?Pf~Q%s)6y`mvXEiihhWWQI}MFCQ1*DK|JWWpj2`07RpQ zlSrrM{?GEuG9i52D?e-WlG&Of^G{SMCaqH2H6(^E;^o)aZN@X*!!oncyg%&f;j=Ba zUTOY!p=#ki%NpC=lIS zKu7YUdKLGoOqr9_Yx-=L)h*_k#cdPSoI1-LYyy1U*iQuztnF-oLhZmdPv{T>C8!GG z!v|Mtg+8!O43YqXTdJ?4SqK8MvJ3l!6s+q9b^t9YaN(*bCY}dnUH41eX?DD5(lu=f zhZW!RV;Ovv3Lv2RrU!y!V2V4t7sVv-!1ICxVjez^tEo>;aIXH(`oY+vpES#@+P<02 zGv6A^JPKx{)_#k$F6|dKYoPk9`q1H6E=Vn$oRmunn^xMI*V3+du_Drs(?N#z02m5wzn2peY=h;W9A2KbRQR}R)G}$7O=`MKd52qj+~s-ZlTyWS_ho&i+H4%mw-{C| zQW%W6ZFlu+p(xDDadUAK-7Og?EP8eRqb-YOF8cUzn@e-0G?VI^M@dM}|(h{*(OaTm^XQ#oWnR88RySo|AA~lbUo!H7tv)e%czLx`W~z#9~oC903IqLx@H;2%A?h>R2c0A{DbvmRD%oX6T+FB