| 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 />
};
```
+## 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
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';
/**
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;
*/
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,
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;
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|%)?)$/);
}
}
}
+
+/**
+ * @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)
+ };
+}
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
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
--- /dev/null
+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
+ }
+ }
+};
--- /dev/null
+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
+ }
+ }
+};
--- /dev/null
+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
+ }
+ }
+};