Ability to fill a line from a specified value along an axis (#7905)

This commit is contained in:
Evert Timberg 2020-10-17 15:46:56 -04:00 committed by GitHub
parent 4a191d5af9
commit c22d3bedea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 117 additions and 8 deletions

View File

@ -15,11 +15,13 @@ Both [line](./line.mdx) and [radar](./radar.mdx) charts support a `fill` option
| Boundary <sup>2</sup> | `string` | `'start'`, `'end'`, `'origin'` |
| Disabled <sup>3</sup> | `boolean` | `false` |
| Stacked value below <sup>4</sup> | `string` | `'stack'` |
| Axis value <sup>5</sup> | `object` | `{ value: number; }` |
> <sup>1</sup> dataset filling modes have been introduced in version 2.6.0<br/>
> <sup>2</sup> prior version 2.6.0, boundary values was `'zero'`, `'top'`, `'bottom'` (not supported anymore)<br/>
> <sup>3</sup> for backward compatibility, `fill: true` (default) is equivalent to `fill: 'origin'`<br/>
> <sup>4</sup> stack mode has been introduced in version 3.0.0<br/>
> <sup>5</sup> axis value mode has been introduced in version 3.0.0<br/>
**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. |

View File

@ -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) {

View File

@ -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}}
}]
};

View File

@ -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},
}]
};

View File

@ -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);

View File

@ -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
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -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
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -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 {
/**