From 30d09f47015e536d91dbb5dd606c2e1a3f38ac75 Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Sat, 17 Oct 2020 16:15:40 -0400 Subject: [PATCH] Bar chart base value overrides (#7904) * Bar chart base value overrides * Ensure that `base` is marked as indexable and scriptable in the docs --- docs/docs/charts/bar.mdx | 3 ++ src/controllers/controller.bar.js | 9 +++-- .../fixtures/controller.bar/bar-base-value.js | 31 ++++++++++++++++++ .../controller.bar/bar-base-value.png | Bin 0 -> 4536 bytes types/elements/index.d.ts | 5 +++ 5 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/controller.bar/bar-base-value.js create mode 100644 test/fixtures/controller.bar/bar-base-value.png diff --git a/docs/docs/charts/bar.mdx b/docs/docs/charts/bar.mdx index 7d0bbbcaa..6fefb7f84 100644 --- a/docs/docs/charts/bar.mdx +++ b/docs/docs/charts/bar.mdx @@ -79,6 +79,7 @@ the color of the bars is generally set this way. | Name | Type | [Scriptable](../general/options.md#scriptable-options) | [Indexable](../general/options.md#indexable-options) | Default | ---- | ---- | :----: | :----: | ---- | [`backgroundColor`](#styling) | [`Color`](../general/colors.md) | Yes | Yes | `'rgba(0, 0, 0, 0.1)'` +| [`base`](#general) | `number` | Yes | Yes | | [`borderColor`](#styling) | [`Color`](../general/colors.md) | Yes | Yes | `'rgba(0, 0, 0, 0.1)'` | [`borderSkipped`](#borderskipped) | `string` | Yes | Yes | `'start'` | [`borderWidth`](#borderwidth) | number|object | Yes | Yes | `0` @@ -97,6 +98,7 @@ the color of the bars is generally set this way. | Name | Description | ---- | ---- +| `base` | Base value for the bar in data units along the value axis. If not set, defaults to the value axis base value. | `clip` | How to clip relative to chartArea. Positive value allows overflow, negative value clips that many pixels inside chartArea. `0` = clip at chartArea. Clipping can also be configured per side: `clip: {left: 5, top: false, right: -2, bottom: 0}` | `indexAxis` | The base axis of the dataset. `'x'` for vertical bars and `'y'` for horizontal bars. | `label` | The label for the dataset which appears in the legend and tooltips. @@ -161,6 +163,7 @@ The bar chart accepts the following configuration from the associated dataset op | `barPercentage` | `number` | `0.9` | Percent (0-1) of the available width each bar should be within the category width. 1.0 will take the whole category width and put the bars right next to each other. [more...](#barpercentage-vs-categorypercentage) | `categoryPercentage` | `number` | `0.8` | Percent (0-1) of the available width each category should be within the sample width. [more...](#barpercentage-vs-categorypercentage) | `barThickness` | number|string | | Manually set width of each bar in pixels. If set to `'flex'`, it computes "optimal" sample widths that globally arrange bars side by side. If not set (default), bars are equally sized based on the smallest interval. [more...](#barthickness) +| `base` | `number` | | Base value for the bar in data units along the value axis. If not set, defaults to the value axis base value. | `maxBarThickness` | `number` | | Set this to ensure that bars are not sized thicker than this. | `minBarLength` | `number` | | Set this to ensure that bars have a minimum length in pixels. diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index aafe80856..173c649cb 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -404,9 +404,10 @@ export default class BarController extends DatasetController { const me = this; const meta = me._cachedMeta; const vScale = meta.vScale; - const minBarLength = options.minBarLength; + const {base: baseValue, minBarLength} = options; const parsed = me.getParsed(index); const custom = parsed._custom; + const floating = isFloatBar(custom); let value = parsed[vScale.axis]; let start = 0; let length = meta._stacked ? me.applyStack(vScale, parsed) : value; @@ -417,7 +418,7 @@ export default class BarController extends DatasetController { length = value; } - if (isFloatBar(custom)) { + if (floating) { value = custom.barStart; length = custom.barEnd - custom.barStart; // bars crossing origin are not stacked @@ -431,7 +432,8 @@ export default class BarController extends DatasetController { // So we don't try to draw so huge rectangles. // https://github.com/chartjs/Chart.js/issues/5247 // TODO: use borderWidth instead (need to move the parsing from rectangle) - let base = _limitValue(vScale.getPixelForValue(start), + const startValue = !isNullOrUndef(baseValue) && !floating ? baseValue : start; + let base = _limitValue(vScale.getPixelForValue(startValue), vScale._startPixel - 10, vScale._endPixel + 10); @@ -521,6 +523,7 @@ BarController.defaults = { 'borderWidth', 'barPercentage', 'barThickness', + 'base', 'categoryPercentage', 'maxBarThickness', 'minBarLength', diff --git a/test/fixtures/controller.bar/bar-base-value.js b/test/fixtures/controller.bar/bar-base-value.js new file mode 100644 index 000000000..0bb96dc6e --- /dev/null +++ b/test/fixtures/controller.bar/bar-base-value.js @@ -0,0 +1,31 @@ +module.exports = { + config: { + type: 'bar', + data: { + labels: [0, 1, 3, 4], + datasets: [ + { + data: [5, 20, 10, 11], + base: 10, + backgroundColor: '#00ff00', + borderColor: '#ff0000', + borderWidth: 2, + } + ] + }, + options: { + legend: false, + title: false, + scales: { + x: {display: false}, + y: {display: false} + } + } + }, + options: { + canvas: { + height: 256, + width: 512 + } + } +}; diff --git a/test/fixtures/controller.bar/bar-base-value.png b/test/fixtures/controller.bar/bar-base-value.png new file mode 100644 index 0000000000000000000000000000000000000000..5d5986bdf86a3398271f10de14c81fd10b4b07bf GIT binary patch literal 4536 zcmeHLT~t$77C!fKLoe5&2_{t;3qgt|p-Kj;$fCeS6x1n_3Wy9VBrZd>)l#hj7L8nV zfI1_UP64et8kRGNfQCV&K$S!t9Y(s;F4r<3$d4>7PLN*%k>Bp*ttT&i=tCcPO3umN z`|O|Z`_5T8s@NFm%D6KKA=mZm)@(wEgs%jmo#Eql{=Mx82{PBO35(sI^s?>AS8vA) zc%5mrkxbY~s>jz$x&(DKYrou&pv1>SCxj%Ng~I)l)F%PBv@A@WDE%ypdcGg^W?@^a~k zSQK*IaL76^IM(MiZ{OD{k=5EYW*Uz+sf1__O^~CE1dTFdllMu6eIBMj{`X4wJNOFZ zzG-%EDWdZA=1mTJBJRy9DYXI4{JZXgDHfGvpS#>oiMw|(SY zhNmttfstNHl|d3^wLcZbq363)Ni6|r!S)#XJt*E)`bJtTA{!eVvjC&5G4v}i3Qjnl zQihHVjX8^N?PRiKki4v~E?L9{CUzjrt|+eui*=~lC!|_W%Bk`HSA~#2tb#PcSYpSz zz{>L^pB)jXom+&Y50te2!NZ+0^zdf1DV@yUvof1K!jTX1KUYWc#9Rf^)p(`Nt>`_hI`_e>=d#9eYJA9zTiD`~@=e)}dFL;QEWC{H|HV z=9q+J93&Cfwzo-!_SX36d;h>4yCS9Bp+PwXPC+t6XrLxM3oxpbQW;=$wjweh4n=&S zb;|ErkR>c_4T>1?8*8nQ!D$rv$&&Tn^{KMMR1W)3lGmwT@hu-_=!sZVN zT0Bn6k3dOoP|`a+FII@SkGn3IgNR0~Wt)+IV+mg(P@oNm&nCqXC*MjV^99haHzTFJqxg@0? z19)owlRFZJa?~p2qeu>?Ag~4#0_%&hjlV)wpkEl$#}Dp-kz>6Eq+s!zeH~y8M%XAv zo)rStF`@!%aBTx444rxa&$SYMsha|oJw2PanK*gH0tkB~BtHd&B|Z%wm!a@V{W7z+ z5vL%q2BYA_KJ5|*)nXi25Bs0@(1E3c#aa>P)f|7qB2eQL1lC{_JXGH>*Fm*- z4y=cMVFDhaYJ-tuatBDk;)8;;)8mY${#Nzu7> z)$|0sjm%M@Ly@X?1_p0gZo%6q-IN+gSQmwbx(jxb@|$Cs^Wtn>Xj`U3Z7He!Dw+Ms z^d$$sl_AZRsJd{LsCDYk3ynkV^z-}6K?Ux#*rr#|$`f*}m-;6E#Oq87GkC&96|n_m z?f2u-v~3obiTd(JYC6W>=v=uZb1jDm(%?5xIqj?FiHA$2c8%eS2d>VNpeDD?sEGGG z&4n-CUCNQWcgPK?iHxzz*tU!yso5e0n(Z1vY~CMbrW1X$ytH6 z8200e0TsnJR?Qqg)BG9e{gQab@L9&SL;Ia!kLB26cnZ(2F9hDR97lF8fDiD?2C3ZIvw5+7!EoDc ndozIv=