From: Evert Timberg Date: Sat, 17 Oct 2020 19:46:56 +0000 (-0400) Subject: Ability to fill a line from a specified value along an axis (#7905) X-Git-Tag: v3.0.0-beta.5~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c22d3bedea902deaaf5021a28d3c113fcc4fa439;p=thirdparty%2FChart.js.git Ability to fill a line from a specified value along an axis (#7905) --- diff --git a/docs/docs/charts/area.md b/docs/docs/charts/area.md index 4ec8edb75..477ece36f 100644 --- a/docs/docs/charts/area.md +++ b/docs/docs/charts/area.md @@ -15,11 +15,13 @@ Both [line](./line.mdx) and [radar](./radar.mdx) charts support a `fill` option | Boundary 2 | `string` | `'start'`, `'end'`, `'origin'` | | Disabled 3 | `boolean` | `false` | | Stacked value below 4 | `string` | `'stack'` | +| Axis value 5 | `object` | `{ value: number; }` | > 1 dataset filling modes have been introduced in version 2.6.0
> 2 prior version 2.6.0, boundary values was `'zero'`, `'top'`, `'bottom'` (not supported anymore)
> 3 for backward compatibility, `fill: true` (default) is equivalent to `fill: 'origin'`
> 4 stack mode has been introduced in version 3.0.0
+> 5 axis value mode has been introduced in version 3.0.0
**Example** @@ -31,7 +33,8 @@ new Chart(ctx, { {fill: '+2'}, // 1: fill to dataset 3 {fill: 1}, // 2: fill to dataset 1 {fill: false}, // 3: no fill - {fill: '-2'} // 4: fill to dataset 2 + {fill: '-2'}, // 4: fill to dataset 2 + {fill: {value: 25}} // 5: fill to axis value 25 ] } }); @@ -41,7 +44,7 @@ If you need to support multiple colors when filling from one dataset to another, | Param | Type | Description | | :--- | :--- | :--- | -| `target` | `number`, `string`, `boolean` | The accepted values are the same as the filling mode values, so you may use absolute and relative dataset indexes and/or boundaries. | +| `target` | `number`, `string`, `boolean`, `object` | The accepted values are the same as the filling mode values, so you may use absolute and relative dataset indexes and/or boundaries. | | `above` | `Color` | If no color is set, the default color will be the background color of the chart. | | `below` | `Color` | Same as the above. | diff --git a/samples/charts/area/analyser.js b/samples/charts/area/analyser.js index 5c1005418..592dcbb9d 100644 --- a/samples/charts/area/analyser.js +++ b/samples/charts/area/analyser.js @@ -48,7 +48,7 @@ } else if (isFinite(target)) { target = 'dataset ' + target; } else { - target = 'boundary "' + target + '"'; + target = 'boundary "' + (typeof target === 'object' ? JSON.stringify(target) : target) + '"'; } if (stat.visible) { diff --git a/samples/charts/area/line-datasets.html b/samples/charts/area/line-datasets.html index 9a6636161..1d1d2706e 100644 --- a/samples/charts/area/line-datasets.html +++ b/samples/charts/area/line-datasets.html @@ -102,6 +102,12 @@ hidden: true, label: 'D8', fill: 'end' + }, { + backgroundColor: utils.transparentize(presets.yellow), + borderColor: presets.yellow, + data: generateData(), + label: 'D9', + fill: {above: 'blue', below: 'red', target: {value: 350}} }] }; diff --git a/samples/charts/area/radar.html b/samples/charts/area/radar.html index de30630ed..3c36d670f 100644 --- a/samples/charts/area/radar.html +++ b/samples/charts/area/radar.html @@ -85,6 +85,12 @@ data: generateData(), label: 'D5', fill: '-1' + }, { + backgroundColor: utils.transparentize(presets.grey), + borderColor: presets.grey, + data: generateData(), + label: 'D6', + fill: {value: 85}, }] }; diff --git a/src/plugins/plugin.filler.js b/src/plugins/plugin.filler.js index c27e4d377..49d2d9ec9 100644 --- a/src/plugins/plugin.filler.js +++ b/src/plugins/plugin.filler.js @@ -7,7 +7,7 @@ import Line from '../elements/element.line'; import {_boundSegment, _boundSegments} from '../helpers/helpers.segment'; import {clipArea, unclipArea} from '../helpers/helpers.canvas'; -import {isArray, isFinite, valueOrDefault} from '../helpers/helpers.core'; +import {isArray, isFinite, isObject, valueOrDefault} from '../helpers/helpers.core'; import {TAU, _normalizeAngle} from '../helpers/helpers.math'; /** @@ -57,7 +57,9 @@ function decodeFill(line, index, count) { const fill = parseFillOption(line); let target = parseFloat(fill); - if (isFinite(target) && Math.floor(target) === target) { + if (isObject(fill)) { + return isNaN(fill.value) ? false : fill; + } else if (isFinite(target) && Math.floor(target) === target) { if (fill[0] === '-' || fill[0] === '+') { target = index + target; } @@ -81,6 +83,8 @@ function computeLinearBoundary(source) { target = scale.bottom; } else if (fill === 'end') { target = scale.top; + } else if (isObject(fill)) { + target = scale.getPixelForValue(fill.value); } else if (scale.getBasePixel) { target = scale.getBasePixel(); } @@ -135,8 +139,17 @@ function computeCircularBoundary(source) { const target = []; const start = options.reverse ? scale.max : scale.min; const end = options.reverse ? scale.min : scale.max; - const value = fill === 'start' ? start : fill === 'end' ? end : scale.getBaseValue(); - let i, center; + let i, center, value; + + if (fill === 'start') { + value = start; + } else if (fill === 'end') { + value = end; + } else if (isObject(fill)) { + value = fill.value; + } else { + value = scale.getBaseValue(); + } if (options.gridLines.circular) { center = scale.getPointPositionForValue(0, start); diff --git a/test/fixtures/plugin.filler/fill-line-value.json b/test/fixtures/plugin.filler/fill-line-value.json new file mode 100644 index 000000000..f8520ea6e --- /dev/null +++ b/test/fixtures/plugin.filler/fill-line-value.json @@ -0,0 +1,42 @@ +{ + "config": { + "type": "line", + "data": { + "labels": ["0", "1", "2", "3", "4", "5", "6", "7", "8"], + "datasets": [{ + "backgroundColor": "rgba(255, 0, 0, 0.25)", + "data": [-4, 4, 0, -1, 0, 1, 0, -1, 0], + "fill": { "value": 2 } + }] + }, + "options": { + "responsive": false, + "spanGaps": false, + "legend": false, + "title": false, + "scales": { + "x": { + "display": false + }, + "y": { + "display": false + } + }, + "elements": { + "point": { + "radius": 0 + }, + "line": { + "borderColor": "transparent", + "tension": 0 + } + } + } + }, + "options": { + "canvas": { + "height": 256, + "width": 512 + } + } +} diff --git a/test/fixtures/plugin.filler/fill-line-value.png b/test/fixtures/plugin.filler/fill-line-value.png new file mode 100644 index 000000000..758b1c132 Binary files /dev/null and b/test/fixtures/plugin.filler/fill-line-value.png differ diff --git a/test/fixtures/plugin.filler/fill-radar-value.json b/test/fixtures/plugin.filler/fill-radar-value.json new file mode 100644 index 000000000..f56be396e --- /dev/null +++ b/test/fixtures/plugin.filler/fill-radar-value.json @@ -0,0 +1,39 @@ +{ + "config": { + "type": "radar", + "data": { + "labels": ["0", "1", "2", "3", "4", "5", "6", "7", "8"], + "datasets": [{ + "backgroundColor": "rgba(0, 0, 192, 0.25)", + "data": [0, -4, 2, 4, 2, 1, -1, 1, 2] + }] + }, + "options": { + "responsive": false, + "spanGaps": false, + "legend": false, + "title": false, + "scale": { + "display": false, + "gridLines": { + "circular": true + } + }, + "elements": { + "point": { + "radius": 0 + }, + "line": { + "borderColor": "transparent", + "fill": { "value": 3 } + } + } + } + }, + "options": { + "canvas": { + "height": 256, + "width": 256 + } + } +} diff --git a/test/fixtures/plugin.filler/fill-radar-value.png b/test/fixtures/plugin.filler/fill-radar-value.png new file mode 100644 index 000000000..f74ee51e4 Binary files /dev/null and b/test/fixtures/plugin.filler/fill-radar-value.png differ diff --git a/types/plugins/index.d.ts b/types/plugins/index.d.ts index 414d3f907..cecf760a1 100644 --- a/types/plugins/index.d.ts +++ b/types/plugins/index.d.ts @@ -9,7 +9,7 @@ export interface IFillerOptions { propagate: boolean; } -export type FillTarget = number | string | 'start' | 'end' | 'origin' | 'stack' | false; +export type FillTarget = number | string | { value: number } | 'start' | 'end' | 'origin' | 'stack' | false; export interface IFillTarget { /**