Skip to content

Commit

Permalink
Add outerRadius option to doughnut/pie (#8487)
Browse files Browse the repository at this point in the history
  • Loading branch information
kurkle committed Feb 21, 2021
1 parent b27a460 commit 65bfacd
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 12 deletions.
1 change: 1 addition & 0 deletions docs/docs/charts/doughnut.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 7 additions & 3 deletions src/controllers/controller.doughnut.js
Original file line number Diff line number Diff line change
@@ -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';

/**
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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',
Expand Down
7 changes: 5 additions & 2 deletions src/controllers/controller.pie.js
Original file line number Diff line number Diff line change
Expand Up @@ -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%'
}
};
5 changes: 5 additions & 0 deletions src/helpers/helpers.core.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
28 changes: 28 additions & 0 deletions test/fixtures/controller.doughnut/doughnut-outer-radius-percent.js
Original file line number Diff line number Diff line change
@@ -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%',
}
}
};
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions test/fixtures/controller.doughnut/doughnut-outer-radius-pixels.js
Original file line number Diff line number Diff line change
@@ -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,
}
}
};
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 13 additions & 7 deletions types/index.esm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,23 +279,29 @@ 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<number | string, ScriptableContext<number>>;

/**
* Starting angle to draw arcs from.
* @default 0
*/
rotation: number;

/**
* Sweep to allow arcs to cover.
* @default 360
*/
circumference: number;

animation: DoughnutAnimationOptions;
}

Expand Down
14 changes: 14 additions & 0 deletions types/tests/controllers/doughnut_outer_radius.ts
Original file line number Diff line number Diff line change
@@ -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%',
}
});

0 comments on commit 65bfacd

Please sign in to comment.