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
|
| Name | Type | Description
|
||||||
| ---- | ---- | -----------
|
| ---- | ---- | -----------
|
||||||
| `beginAtZero` | `boolean` | if true, scale will include 0 if it is not already included.
|
| `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 />
|
<CommonCartesian />
|
||||||
<CommonAll />
|
<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
|
## Internal data format
|
||||||
|
|
||||||
Internally, the linear scale uses numeric data
|
Internally, the linear scale uses numeric data
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import DatasetController from '../core/core.datasetController';
|
import DatasetController from '../core/core.datasetController';
|
||||||
import {formatNumber} from '../core/core.intl';
|
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';
|
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 maxWidth = (chartArea.width - spacing) / ratioX;
|
||||||
const maxHeight = (chartArea.height - spacing) / ratioY;
|
const maxHeight = (chartArea.height - spacing) / ratioY;
|
||||||
const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0);
|
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 innerRadius = Math.max(outerRadius * cutout, 0);
|
||||||
const radiusLength = (outerRadius - innerRadius) / me._getVisibleDatasetWeightTotal();
|
const radiusLength = (outerRadius - innerRadius) / me._getVisibleDatasetWeightTotal();
|
||||||
me.offsetX = offsetX * outerRadius;
|
me.offsetX = offsetX * outerRadius;
|
||||||
|
|||||||
@ -26,6 +26,12 @@ defaults.set('scale', {
|
|||||||
*/
|
*/
|
||||||
bounds: 'ticks',
|
bounds: 'ticks',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Addition grace added to max and reduced from min data value.
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
grace: 0,
|
||||||
|
|
||||||
// grid line settings
|
// grid line settings
|
||||||
gridLines: {
|
gridLines: {
|
||||||
display: true,
|
display: true,
|
||||||
|
|||||||
@ -90,7 +90,7 @@ export const toPercentage = (value, dimension) =>
|
|||||||
parseFloat(value) / 100
|
parseFloat(value) / 100
|
||||||
: value / dimension;
|
: value / dimension;
|
||||||
|
|
||||||
export const toPixels = (value, dimension) =>
|
export const toDimension = (value, dimension) =>
|
||||||
typeof value === 'string' && value.endsWith('%') ?
|
typeof value === 'string' && value.endsWith('%') ?
|
||||||
parseFloat(value) / 100 * dimension
|
parseFloat(value) / 100 * dimension
|
||||||
: +value;
|
: +value;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import defaults from '../core/core.defaults';
|
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';
|
import {toFontString} from './helpers.canvas';
|
||||||
|
|
||||||
const LINE_HEIGHT = new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);
|
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 {almostEquals, almostWhole, niceNum, _decimalPlaces, _setMinAndMaxByKey, sign} from '../helpers/helpers.math';
|
||||||
import Scale from '../core/core.scale';
|
import Scale from '../core/core.scale';
|
||||||
import {formatNumber} from '../core/core.intl';
|
import {formatNumber} from '../core/core.intl';
|
||||||
|
import {_addGrace} from '../helpers/helpers.options';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a set of linear ticks
|
* Generate a set of linear ticks
|
||||||
@ -205,7 +206,7 @@ export default class LinearScaleBase extends Scale {
|
|||||||
precision: tickOpts.precision,
|
precision: tickOpts.precision,
|
||||||
stepSize: tickOpts.stepSize
|
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,
|
// 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
|
// 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