mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Add grace option for linear scale (#8581)
* Add `grace` option for linear scale * cc
This commit is contained in:
parent
1e6a3fb8e6
commit
7ccf9e2d4d
@ -18,6 +18,7 @@ Namespace: `options.scales[scaleId]`
|
||||
| Name | Type | Description
|
||||
| ---- | ---- | -----------
|
||||
| `beginAtZero` | `boolean` | if true, scale will include 0 if it is not already included.
|
||||
| `grace` | `number`\|`string` | Percentage (string ending with `%`) or amount (number) for added room in the scale range above and below data. [more...](#grace)
|
||||
|
||||
<CommonCartesian />
|
||||
<CommonAll />
|
||||
@ -58,6 +59,45 @@ let options = {
|
||||
};
|
||||
```
|
||||
|
||||
## Grace
|
||||
|
||||
If the value is string ending with `%`, its treat as percentage. If number, its treat as value.
|
||||
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.
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
```jsx live
|
||||
function example() {
|
||||
const canvas = useRef(null);
|
||||
useEffect(() => {
|
||||
const cfg = {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ['Positive', 'Negative'],
|
||||
datasets: [{
|
||||
data: [100, -50],
|
||||
backgroundColor: 'rgb(255, 99, 132)'
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
type: 'linear',
|
||||
grace: '5%'
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: false
|
||||
}
|
||||
}
|
||||
};
|
||||
const chart = new Chart(canvas.current.getContext('2d'), cfg);
|
||||
return () => chart.destroy();
|
||||
});
|
||||
return <div className="chartjs-wrapper"><canvas ref={canvas} className="chartjs"></canvas></div>;
|
||||
}
|
||||
```
|
||||
|
||||
## Internal data format
|
||||
|
||||
Internally, the linear scale uses numeric data
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import DatasetController from '../core/core.datasetController';
|
||||
import {formatNumber} from '../core/core.intl';
|
||||
import {isArray, toPercentage, toPixels, valueOrDefault} from '../helpers/helpers.core';
|
||||
import {isArray, toPercentage, toDimension, valueOrDefault} from '../helpers/helpers.core';
|
||||
import {toRadians, PI, TAU, HALF_PI, _angleBetween} from '../helpers/helpers.math';
|
||||
|
||||
/**
|
||||
@ -123,7 +123,7 @@ export default class DoughnutController extends DatasetController {
|
||||
const maxWidth = (chartArea.width - spacing) / ratioX;
|
||||
const maxHeight = (chartArea.height - spacing) / ratioY;
|
||||
const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0);
|
||||
const outerRadius = toPixels(me.options.radius, maxRadius);
|
||||
const outerRadius = toDimension(me.options.radius, maxRadius);
|
||||
const innerRadius = Math.max(outerRadius * cutout, 0);
|
||||
const radiusLength = (outerRadius - innerRadius) / me._getVisibleDatasetWeightTotal();
|
||||
me.offsetX = offsetX * outerRadius;
|
||||
|
||||
@ -26,6 +26,12 @@ defaults.set('scale', {
|
||||
*/
|
||||
bounds: 'ticks',
|
||||
|
||||
/**
|
||||
* Addition grace added to max and reduced from min data value.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
grace: 0,
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
display: true,
|
||||
|
||||
@ -90,7 +90,7 @@ export const toPercentage = (value, dimension) =>
|
||||
parseFloat(value) / 100
|
||||
: value / dimension;
|
||||
|
||||
export const toPixels = (value, dimension) =>
|
||||
export const toDimension = (value, dimension) =>
|
||||
typeof value === 'string' && value.endsWith('%') ?
|
||||
parseFloat(value) / 100 * dimension
|
||||
: +value;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import defaults from '../core/core.defaults';
|
||||
import {isArray, isObject, valueOrDefault} from './helpers.core';
|
||||
import {isArray, isObject, toDimension, valueOrDefault} from './helpers.core';
|
||||
import {toFontString} from './helpers.canvas';
|
||||
|
||||
const LINE_HEIGHT = new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);
|
||||
@ -175,3 +175,16 @@ export function resolve(inputs, context, index, info) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{min: number, max: number}} minmax
|
||||
* @param {number|string} grace
|
||||
* @private
|
||||
*/
|
||||
export function _addGrace(minmax, grace) {
|
||||
const {min, max} = minmax;
|
||||
return {
|
||||
min: min - Math.abs(toDimension(grace, min)),
|
||||
max: max + toDimension(grace, max)
|
||||
};
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import {isNullOrUndef} from '../helpers/helpers.core';
|
||||
import {almostEquals, almostWhole, niceNum, _decimalPlaces, _setMinAndMaxByKey, sign} from '../helpers/helpers.math';
|
||||
import Scale from '../core/core.scale';
|
||||
import {formatNumber} from '../core/core.intl';
|
||||
import {_addGrace} from '../helpers/helpers.options';
|
||||
|
||||
/**
|
||||
* Generate a set of linear ticks
|
||||
@ -205,7 +206,7 @@ export default class LinearScaleBase extends Scale {
|
||||
precision: tickOpts.precision,
|
||||
stepSize: tickOpts.stepSize
|
||||
};
|
||||
const ticks = generateTicks(numericGeneratorOptions, me);
|
||||
const ticks = generateTicks(numericGeneratorOptions, _addGrace(me, opts.grace));
|
||||
|
||||
// At this point, we need to update our max and min given the tick values,
|
||||
// since we probably have expanded the range of the scale
|
||||
|
||||
30
test/fixtures/scale.linear/grace-neg.js
vendored
Normal file
30
test/fixtures/scale.linear/grace-neg.js
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
module.exports = {
|
||||
description: 'https://github.com/chartjs/Chart.js/issues/7734',
|
||||
config: {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ['a'],
|
||||
datasets: [{
|
||||
data: [-0.18],
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
indexAxis: 'y',
|
||||
scales: {
|
||||
y: {
|
||||
display: false
|
||||
},
|
||||
x: {
|
||||
grace: '5%'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
options: {
|
||||
spriteText: true,
|
||||
canvas: {
|
||||
width: 512,
|
||||
height: 128
|
||||
}
|
||||
}
|
||||
};
|
||||
BIN
test/fixtures/scale.linear/grace-neg.png
vendored
Normal file
BIN
test/fixtures/scale.linear/grace-neg.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
30
test/fixtures/scale.linear/grace-pos.js
vendored
Normal file
30
test/fixtures/scale.linear/grace-pos.js
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
module.exports = {
|
||||
description: 'https://github.com/chartjs/Chart.js/issues/7734',
|
||||
config: {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ['a'],
|
||||
datasets: [{
|
||||
data: [0.18],
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
indexAxis: 'y',
|
||||
scales: {
|
||||
y: {
|
||||
display: false
|
||||
},
|
||||
x: {
|
||||
grace: '5%'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
options: {
|
||||
spriteText: true,
|
||||
canvas: {
|
||||
width: 512,
|
||||
height: 128
|
||||
}
|
||||
}
|
||||
};
|
||||
BIN
test/fixtures/scale.linear/grace-pos.png
vendored
Normal file
BIN
test/fixtures/scale.linear/grace-pos.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
30
test/fixtures/scale.linear/grace.js
vendored
Normal file
30
test/fixtures/scale.linear/grace.js
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
module.exports = {
|
||||
description: 'https://github.com/chartjs/Chart.js/issues/7734',
|
||||
config: {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ['a', 'b'],
|
||||
datasets: [{
|
||||
data: [1.2, -0.2],
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
indexAxis: 'y',
|
||||
scales: {
|
||||
y: {
|
||||
display: false
|
||||
},
|
||||
x: {
|
||||
grace: 0.3
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
options: {
|
||||
spriteText: true,
|
||||
canvas: {
|
||||
width: 512,
|
||||
height: 128
|
||||
}
|
||||
}
|
||||
};
|
||||
BIN
test/fixtures/scale.linear/grace.png
vendored
Normal file
BIN
test/fixtures/scale.linear/grace.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
Loading…
x
Reference in New Issue
Block a user