From: Jukka Kurkela Date: Sun, 21 Feb 2021 22:30:37 +0000 (+0200) Subject: Add outerRadius option to doughnut/pie (#8487) X-Git-Tag: v3.0.0-beta.12~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=65bfacd9a59a1dd3ee6b67f3968aa9e12423fec6;p=thirdparty%2FChart.js.git Add outerRadius option to doughnut/pie (#8487) --- diff --git a/docs/docs/charts/doughnut.mdx b/docs/docs/charts/doughnut.mdx index a9b929eb4..b2b69e30f 100644 --- a/docs/docs/charts/doughnut.mdx +++ b/docs/docs/charts/doughnut.mdx @@ -164,6 +164,7 @@ These are the customisation options specific to Pie & Doughnut charts. These opt | Name | Type | Default | Description | ---- | ---- | ------- | ----------- | `cutoutPercentage` | `number` | `50` - for doughnut, `0` - for pie | The percentage of the chart that is cut out of the middle. +| `outerRadius` | `number`\|`string` | `100%` | The outer radius of the chart. If `string` and ending with '%', percentage of the maximum radius. `number` is considered to be pixels. | `rotation` | `number` | 0 | Starting angle to draw arcs from. | `circumference` | `number` | 360 | Sweep to allow arcs to cover. | `animation.animateRotate` | `boolean` | `true` | If true, the chart will animate in with a rotation animation. This property is in the `options.animation` object. diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js index c283a266a..2f013c0cf 100644 --- a/src/controllers/controller.doughnut.js +++ b/src/controllers/controller.doughnut.js @@ -1,6 +1,6 @@ import DatasetController from '../core/core.datasetController'; import {formatNumber} from '../core/core.intl'; -import {isArray, valueOrDefault} from '../helpers/helpers.core'; +import {isArray, numberOrPercentageOf, valueOrDefault} from '../helpers/helpers.core'; import {toRadians, PI, TAU, HALF_PI} from '../helpers/helpers.math'; /** @@ -138,7 +138,8 @@ export default class DoughnutController extends DatasetController { const spacing = me.getMaxBorderWidth() + me.getMaxOffset(arcs); const maxWidth = (chartArea.right - chartArea.left - spacing) / ratioX; const maxHeight = (chartArea.bottom - chartArea.top - spacing) / ratioY; - const outerRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0); + const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0); + const outerRadius = numberOrPercentageOf(me.options.outerRadius, maxRadius); const innerRadius = Math.max(outerRadius * cutout, 0); const radiusLength = (outerRadius - innerRadius) / me._getVisibleDatasetWeightTotal(); me.offsetX = offsetX * outerRadius; @@ -350,7 +351,10 @@ DoughnutController.defaults = { rotation: 0, // The total circumference of the chart. - circumference: 360 + circumference: 360, + + // The outr radius of the chart + outerRadius: '100%' }, indexAxis: 'r', diff --git a/src/controllers/controller.pie.js b/src/controllers/controller.pie.js index c88a3cbc3..f0162ef2d 100644 --- a/src/controllers/controller.pie.js +++ b/src/controllers/controller.pie.js @@ -13,12 +13,15 @@ PieController.id = 'pie'; PieController.defaults = { datasets: { // The percentage of the chart that we cut out of the middle. - cutoutPercentage: 0, + cutout: 0, // The rotation of the chart, where the first data arc begins. rotation: 0, // The total circumference of the chart. - circumference: 360 + circumference: 360, + + // The outr radius of the chart + outerRadius: '100%' } }; diff --git a/src/helpers/helpers.core.js b/src/helpers/helpers.core.js index 159c1335c..f670065c3 100644 --- a/src/helpers/helpers.core.js +++ b/src/helpers/helpers.core.js @@ -85,6 +85,11 @@ export function valueOrDefault(value, defaultValue) { return typeof value === 'undefined' ? defaultValue : value; } +export const numberOrPercentageOf = (value, dimension) => + typeof value === 'string' && value.endsWith('%') ? + parseFloat(value) / 100 * dimension + : +value; + /** * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the * value returned by `fn`. If `fn` is not a function, this method returns undefined. diff --git a/test/fixtures/controller.doughnut/doughnut-outer-radius-percent.js b/test/fixtures/controller.doughnut/doughnut-outer-radius-percent.js new file mode 100644 index 000000000..28dd46da0 --- /dev/null +++ b/test/fixtures/controller.doughnut/doughnut-outer-radius-percent.js @@ -0,0 +1,28 @@ +module.exports = { + config: { + type: 'doughnut', + data: { + labels: ['A', 'B', 'C', 'D', 'E'], + datasets: [{ + data: [1, 5, 10, 50, 100], + backgroundColor: [ + 'rgba(255, 99, 132, 0.8)', + 'rgba(54, 162, 235, 0.8)', + 'rgba(255, 206, 86, 0.8)', + 'rgba(75, 192, 192, 0.8)', + 'rgba(153, 102, 255, 0.8)' + ], + borderColor: [ + 'rgb(255, 99, 132)', + 'rgb(54, 162, 235)', + 'rgb(255, 206, 86)', + 'rgb(75, 192, 192)', + 'rgb(153, 102, 255)' + ] + }] + }, + options: { + outerRadius: '30%', + } + } +}; diff --git a/test/fixtures/controller.doughnut/doughnut-outer-radius-percent.png b/test/fixtures/controller.doughnut/doughnut-outer-radius-percent.png new file mode 100644 index 000000000..f2f0dcdff Binary files /dev/null and b/test/fixtures/controller.doughnut/doughnut-outer-radius-percent.png differ diff --git a/test/fixtures/controller.doughnut/doughnut-outer-radius-pixels.js b/test/fixtures/controller.doughnut/doughnut-outer-radius-pixels.js new file mode 100644 index 000000000..a4a50df23 --- /dev/null +++ b/test/fixtures/controller.doughnut/doughnut-outer-radius-pixels.js @@ -0,0 +1,28 @@ +module.exports = { + config: { + type: 'doughnut', + data: { + labels: ['A', 'B', 'C', 'D', 'E'], + datasets: [{ + data: [1, 5, 10, 50, 100], + backgroundColor: [ + 'rgba(255, 99, 132, 0.8)', + 'rgba(54, 162, 235, 0.8)', + 'rgba(255, 206, 86, 0.8)', + 'rgba(75, 192, 192, 0.8)', + 'rgba(153, 102, 255, 0.8)' + ], + borderColor: [ + 'rgb(255, 99, 132)', + 'rgb(54, 162, 235)', + 'rgb(255, 206, 86)', + 'rgb(75, 192, 192)', + 'rgb(153, 102, 255)' + ] + }] + }, + options: { + outerRadius: 150, + } + } +}; diff --git a/test/fixtures/controller.doughnut/doughnut-outer-radius-pixels.png b/test/fixtures/controller.doughnut/doughnut-outer-radius-pixels.png new file mode 100644 index 000000000..195218cab Binary files /dev/null and b/test/fixtures/controller.doughnut/doughnut-outer-radius-pixels.png differ diff --git a/types/index.esm.d.ts b/types/index.esm.d.ts index cee5be46e..a2933237c 100644 --- a/types/index.esm.d.ts +++ b/types/index.esm.d.ts @@ -279,10 +279,22 @@ export interface DoughnutAnimationOptions { export interface DoughnutControllerChartOptions { /** + * Sweep to allow arcs to cover. + * @default 360 + */ + circumference: number; + + /** * The percentage of the chart that is cut out of the middle. (50 - for doughnut, 0 - for pie) * @default 50 */ - cutoutPercentage: number; + cutoutPercentage: number; + + /** + * The outer radius of the chart. String ending with '%' means percentage of maximum radius, number means pixels. + * @default '100%' + */ + outerRadius: Scriptable>; /** * Starting angle to draw arcs from. @@ -290,12 +302,6 @@ export interface DoughnutControllerChartOptions { */ rotation: number; - /** - * Sweep to allow arcs to cover. - * @default 360 - */ - circumference: number; - animation: DoughnutAnimationOptions; } diff --git a/types/tests/controllers/doughnut_outer_radius.ts b/types/tests/controllers/doughnut_outer_radius.ts new file mode 100644 index 000000000..2c1dd73b7 --- /dev/null +++ b/types/tests/controllers/doughnut_outer_radius.ts @@ -0,0 +1,14 @@ +import { Chart } from '../../index.esm'; + +const chart = new Chart('id', { + type: 'doughnut', + data: { + labels: [], + datasets: [{ + data: [], + }] + }, + options: { + outerRadius: () => Math.random() > 0.5 ? 50 : '50%', + } +});