Skip to content

Commit 7ccf9e2

Browse files
authored
Add grace option for linear scale (#8581)
* Add `grace` option for linear scale * cc
1 parent 1e6a3fb commit 7ccf9e2

File tree

12 files changed

+155
-5
lines changed

12 files changed

+155
-5
lines changed

docs/docs/axes/cartesian/linear.mdx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Namespace: `options.scales[scaleId]`
1818
| Name | Type | Description
1919
| ---- | ---- | -----------
2020
| `beginAtZero` | `boolean` | if true, scale will include 0 if it is not already included.
21+
| `grace` | `number`\|`string` | Percentage (string ending with `%`) or amount (number) for added room in the scale range above and below data. [more...](#grace)
2122

2223
<CommonCartesian />
2324
<CommonAll />
@@ -58,6 +59,45 @@ let options = {
5859
};
5960
```
6061

62+
## Grace
63+
64+
If the value is string ending with `%`, its treat as percentage. If number, its treat as value.
65+
The value is added to the maximum data value and subtracted from the minumum data. This extends the scale range as if the data values were that much greater.
66+
67+
import { useEffect, useRef } from 'react';
68+
69+
```jsx live
70+
function example() {
71+
const canvas = useRef(null);
72+
useEffect(() => {
73+
const cfg = {
74+
type: 'bar',
75+
data: {
76+
labels: ['Positive', 'Negative'],
77+
datasets: [{
78+
data: [100, -50],
79+
backgroundColor: 'rgb(255, 99, 132)'
80+
}],
81+
},
82+
options: {
83+
scales: {
84+
y: {
85+
type: 'linear',
86+
grace: '5%'
87+
}
88+
},
89+
plugins: {
90+
legend: false
91+
}
92+
}
93+
};
94+
const chart = new Chart(canvas.current.getContext('2d'), cfg);
95+
return () => chart.destroy();
96+
});
97+
return <div className="chartjs-wrapper"><canvas ref={canvas} className="chartjs"></canvas></div>;
98+
}
99+
```
100+
61101
## Internal data format
62102

63103
Internally, the linear scale uses numeric data

src/controllers/controller.doughnut.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import DatasetController from '../core/core.datasetController';
22
import {formatNumber} from '../core/core.intl';
3-
import {isArray, toPercentage, toPixels, valueOrDefault} from '../helpers/helpers.core';
3+
import {isArray, toPercentage, toDimension, valueOrDefault} from '../helpers/helpers.core';
44
import {toRadians, PI, TAU, HALF_PI, _angleBetween} from '../helpers/helpers.math';
55

66
/**
@@ -123,7 +123,7 @@ export default class DoughnutController extends DatasetController {
123123
const maxWidth = (chartArea.width - spacing) / ratioX;
124124
const maxHeight = (chartArea.height - spacing) / ratioY;
125125
const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0);
126-
const outerRadius = toPixels(me.options.radius, maxRadius);
126+
const outerRadius = toDimension(me.options.radius, maxRadius);
127127
const innerRadius = Math.max(outerRadius * cutout, 0);
128128
const radiusLength = (outerRadius - innerRadius) / me._getVisibleDatasetWeightTotal();
129129
me.offsetX = offsetX * outerRadius;

src/core/core.scale.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ defaults.set('scale', {
2626
*/
2727
bounds: 'ticks',
2828

29+
/**
30+
* Addition grace added to max and reduced from min data value.
31+
* @since 3.0.0
32+
*/
33+
grace: 0,
34+
2935
// grid line settings
3036
gridLines: {
3137
display: true,

src/helpers/helpers.core.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export const toPercentage = (value, dimension) =>
9090
parseFloat(value) / 100
9191
: value / dimension;
9292

93-
export const toPixels = (value, dimension) =>
93+
export const toDimension = (value, dimension) =>
9494
typeof value === 'string' && value.endsWith('%') ?
9595
parseFloat(value) / 100 * dimension
9696
: +value;

src/helpers/helpers.options.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import defaults from '../core/core.defaults';
2-
import {isArray, isObject, valueOrDefault} from './helpers.core';
2+
import {isArray, isObject, toDimension, valueOrDefault} from './helpers.core';
33
import {toFontString} from './helpers.canvas';
44

55
const LINE_HEIGHT = new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);
@@ -175,3 +175,16 @@ export function resolve(inputs, context, index, info) {
175175
}
176176
}
177177
}
178+
179+
/**
180+
* @param {{min: number, max: number}} minmax
181+
* @param {number|string} grace
182+
* @private
183+
*/
184+
export function _addGrace(minmax, grace) {
185+
const {min, max} = minmax;
186+
return {
187+
min: min - Math.abs(toDimension(grace, min)),
188+
max: max + toDimension(grace, max)
189+
};
190+
}

src/scales/scale.linearbase.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {isNullOrUndef} from '../helpers/helpers.core';
22
import {almostEquals, almostWhole, niceNum, _decimalPlaces, _setMinAndMaxByKey, sign} from '../helpers/helpers.math';
33
import Scale from '../core/core.scale';
44
import {formatNumber} from '../core/core.intl';
5+
import {_addGrace} from '../helpers/helpers.options';
56

67
/**
78
* Generate a set of linear ticks
@@ -205,7 +206,7 @@ export default class LinearScaleBase extends Scale {
205206
precision: tickOpts.precision,
206207
stepSize: tickOpts.stepSize
207208
};
208-
const ticks = generateTicks(numericGeneratorOptions, me);
209+
const ticks = generateTicks(numericGeneratorOptions, _addGrace(me, opts.grace));
209210

210211
// At this point, we need to update our max and min given the tick values,
211212
// since we probably have expanded the range of the scale
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module.exports = {
2+
description: 'https://github.com/chartjs/Chart.js/issues/7734',
3+
config: {
4+
type: 'bar',
5+
data: {
6+
labels: ['a'],
7+
datasets: [{
8+
data: [-0.18],
9+
}],
10+
},
11+
options: {
12+
indexAxis: 'y',
13+
scales: {
14+
y: {
15+
display: false
16+
},
17+
x: {
18+
grace: '5%'
19+
}
20+
}
21+
}
22+
},
23+
options: {
24+
spriteText: true,
25+
canvas: {
26+
width: 512,
27+
height: 128
28+
}
29+
}
30+
};
6.59 KB
Loading
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module.exports = {
2+
description: 'https://github.com/chartjs/Chart.js/issues/7734',
3+
config: {
4+
type: 'bar',
5+
data: {
6+
labels: ['a'],
7+
datasets: [{
8+
data: [0.18],
9+
}],
10+
},
11+
options: {
12+
indexAxis: 'y',
13+
scales: {
14+
y: {
15+
display: false
16+
},
17+
x: {
18+
grace: '5%'
19+
}
20+
}
21+
}
22+
},
23+
options: {
24+
spriteText: true,
25+
canvas: {
26+
width: 512,
27+
height: 128
28+
}
29+
}
30+
};
5.16 KB
Loading

0 commit comments

Comments
 (0)