From: Jukka Kurkela Date: Sun, 7 Mar 2021 15:52:31 +0000 (+0200) Subject: Add `'single'` mode for stacking (#8586) X-Git-Tag: v3.0.0-beta.14~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=160534f91389017600d6e879022a020125951b06;p=thirdparty%2FChart.js.git Add `'single'` mode for stacking (#8586) * Add `'single'` mode for stacking * Update fixture --- diff --git a/docs/docs/axes/_common.md b/docs/docs/axes/_common.md index b0ca57018..9e3546461 100644 --- a/docs/docs/axes/_common.md +++ b/docs/docs/axes/_common.md @@ -10,6 +10,7 @@ Namespace: `options.scales[scaleId]` | `min` | `number` | | User defined minimum number for the scale, overrides minimum value from data. [more...](./index.mdx#axis-range-settings) | `max` | `number` | | User defined maximum number for the scale, overrides maximum value from data. [more...](./index.mdx#axis-range-settings) | `reverse` | `boolean` | `false` | Reverse the scale. +| `stacked` | `boolean`\|`string` | `false` | Should the data be stacked. [more...](./index.mdx#stacking) | `suggestedMax` | `number` | | Adjustment used when calculating the maximum data value. [more...](./index.mdx#axis-range-settings) | `suggestedMin` | `number` | | Adjustment used when calculating the minimum data value. [more...](./index.mdx#axis-range-settings) | `ticks` | `object` | | Tick configuration. [more...](#tick-configuration) diff --git a/docs/docs/axes/index.mdx b/docs/docs/axes/index.mdx index 7a83229de..0d7be61cc 100644 --- a/docs/docs/axes/index.mdx +++ b/docs/docs/axes/index.mdx @@ -60,7 +60,12 @@ let chart = new Chart(ctx, { In contrast to the `suggested*` settings, the `min` and `max` settings set explicit ends to the axes. When these are set, some data points may not be visible. -### Callbacks +## Stacking + +By default data is not stacked. If the `stacked` option of the value scale (y-axis on horizontal chart) is `true`, positive and negative values are stacked separately. Additionally a `stack` option can be defined per dataset to further divide into stack groups [more...](../general/data-structures/#dataset-configuration). +For some charts, you might want to stack positive and negative values together. That can be achieved by specifying `stacked: 'single'`. + +## Callbacks There are a number of config callbacks that can be used to change parameters in the scale at different points in the update process. The options are supplied at the top level of the axis options. diff --git a/docs/docs/charts/area.md b/docs/docs/charts/area.md index 31d0e4a8a..a29b71e9a 100644 --- a/docs/docs/charts/area.md +++ b/docs/docs/charts/area.md @@ -14,7 +14,7 @@ Both [line](./line.mdx) and [radar](./radar.mdx) charts support a `fill` option | Relative dataset index | `string` | `'-1'`, `'-2'`, `'+1'`, ... | | Boundary | `string` | `'start'`, `'end'`, `'origin'` | | Disabled 1 | `boolean` | `false` | -| Stacked value below 4 | `string` | `'stack'` | +| Stacked value below | `string` | `'stack'` | | Axis value | `object` | `{ value: number; }` | > 1 for backward compatibility, `fill: true` is equivalent to `fill: 'origin'`
diff --git a/samples/charts/area/line-stacked.html b/samples/charts/area/line-stacked.html index d74db4876..eaee5f0a4 100644 --- a/samples/charts/area/line-stacked.html +++ b/samples/charts/area/line-stacked.html @@ -19,6 +19,10 @@
+
+ +
+

@@ -27,81 +31,84 @@ diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index 9bf5ef32e..2a8c6c8e0 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -401,15 +401,14 @@ export default class BarController extends DatasetController { */ _calculateBarValuePixels(index) { const me = this; - const meta = me._cachedMeta; - const vScale = meta.vScale; + const {vScale, _stacked} = me._cachedMeta; const {base: baseValue, minBarLength} = me.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; + let length = _stacked ? me.applyStack(vScale, parsed, _stacked) : value; let head, size; if (length !== value) { diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js index ca56046e8..82b8894dd 100644 --- a/src/controllers/controller.line.js +++ b/src/controllers/controller.line.js @@ -62,7 +62,7 @@ export default class LineController extends DatasetController { const parsed = me.getParsed(i); const properties = directUpdate ? point : {}; const x = properties.x = xScale.getPixelForValue(parsed.x, i); - const y = properties.y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(_stacked ? me.applyStack(yScale, parsed) : parsed.y, i); + const y = properties.y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(_stacked ? me.applyStack(yScale, parsed, _stacked) : parsed.y, i); properties.skip = isNaN(x) || isNaN(y); properties.stop = i > 0 && (parsed.x - prevParsed.x) > maxGapLength; diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js index ba1156444..f33cb6da9 100644 --- a/src/core/core.datasetController.js +++ b/src/core/core.datasetController.js @@ -66,8 +66,9 @@ function getSortedDatasetIndices(chart, filterVisible) { return keys; } -function applyStack(stack, value, dsIndex, allOther) { +function applyStack(stack, value, dsIndex, options) { const keys = stack.keys; + const singleMode = options.mode === 'single'; let i, ilen, datasetIndex, otherValue; if (value === null) { @@ -77,13 +78,13 @@ function applyStack(stack, value, dsIndex, allOther) { for (i = 0, ilen = keys.length; i < ilen; ++i) { datasetIndex = +keys[i]; if (datasetIndex === dsIndex) { - if (allOther) { + if (options.all) { continue; } break; } otherValue = stack.values[datasetIndex]; - if (isFinite(otherValue) && (value === 0 || sign(value) === sign(otherValue))) { + if (isFinite(otherValue) && (singleMode || (value === 0 || sign(value) === sign(otherValue)))) { value += otherValue; } } @@ -517,7 +518,7 @@ export default class DatasetController { /** * @protected */ - applyStack(scale, parsed) { + applyStack(scale, parsed, mode) { const chart = this.chart; const meta = this._cachedMeta; const value = parsed[scale.axis]; @@ -525,7 +526,7 @@ export default class DatasetController { keys: getSortedDatasetIndices(chart, true), values: parsed._stacks[scale.axis] }; - return applyStack(stack, value, meta.index); + return applyStack(stack, value, meta.index, {mode}); } /** @@ -541,7 +542,7 @@ export default class DatasetController { // in addition to the stacked value range.min = Math.min(range.min, value); range.max = Math.max(range.max, value); - value = applyStack(stack, parsedValue, this._cachedMeta.index, true); + value = applyStack(stack, parsedValue, this._cachedMeta.index, {all: true}); } range.min = Math.min(range.min, value); range.max = Math.max(range.max, value); diff --git a/test/fixtures/controller.line/stacking/single.js b/test/fixtures/controller.line/stacking/single.js new file mode 100644 index 000000000..92519880f --- /dev/null +++ b/test/fixtures/controller.line/stacking/single.js @@ -0,0 +1,51 @@ +module.exports = { + config: { + type: 'line', + data: { + labels: [0, 1, 2], + datasets: [ + { + data: [0, -1, -1], + backgroundColor: '#ff0000', + }, + { + data: [0, 2, 2], + backgroundColor: '#00ff00', + }, + { + data: [0, 0, 1], + backgroundColor: '#0000ff', + } + ] + }, + options: { + elements: { + line: { + fill: '-1', + }, + point: { + radius: 0 + } + }, + layout: { + padding: 32 + }, + plugins: { + legend: false, + title: false, + tooltip: false, + filler: true + }, + scales: { + x: {display: false}, + y: {display: false, stacked: 'single'} + } + } + }, + options: { + canvas: { + height: 256, + width: 512 + } + } +}; diff --git a/test/fixtures/controller.line/stacking/single.png b/test/fixtures/controller.line/stacking/single.png new file mode 100644 index 000000000..595773cc4 Binary files /dev/null and b/test/fixtures/controller.line/stacking/single.png differ diff --git a/types/index.esm.d.ts b/types/index.esm.d.ts index 4052e0d1f..7d59db582 100644 --- a/types/index.esm.d.ts +++ b/types/index.esm.d.ts @@ -427,7 +427,7 @@ export interface ChartMeta