Skip to content

Commit 938ef5c

Browse files
authored
Enable centered label drawing for doughnut controllers (#825)
* Enable centered label drawing for doughnut controllers * InnerLabel uses the label annotation * moves code in afterUpdate hook * adds listeners to events * changes context type for innerlabel * moves to a specific element for doughnut inner label * removes specific context type for innerlabel * fixes returned properties when there is not any doughnut controller * removes inner label plugin and all managed by annotaiton one * adds js doc and fix some CC issues * improves controller retriever * creates helpers.callout * fixes visibility check on elements * test cases * improves filter on array and more tests * types def * add documentation * fix lint * add samples * fixes animations and options * no extension from label and background not a box but arc * aply some reviews * lint * fixes test cases * fixes color animation * fixes font and colors options as indexable * adds new test cases for background * fixes types * fixes docs and samples * CC and color animations * change doc about animations * apply new features coming from other PRs after merging * adds test cases for init animation * apply review * fix lineHeight on multiple font when size must be updated by fit ratio * add hitTolerance * apply review
1 parent 1702e13 commit 938ef5c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+1918
-180
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ For Chart.js 2.4.0 to 2.9.x support, use [version 0.5.7 of this plugin](https://
2121

2222
This plugin draws lines, boxes, points, labels, polygons and ellipses on the chart area.
2323

24-
Annotations work with line, bar, scatter and bubble charts that use linear, logarithmic, time, or category scales. Annotations will not work on any chart that does not have two or more axes, including pie, radar, and polar area charts.
24+
Annotations work with line, bar, scatter and bubble charts that use linear, logarithmic, time, or category scales.
25+
Furthermore you can use a doughnut label annotation which can be used to add contents (text, image, canvas) in the middle area of the doughnut charts.
2526

2627
![Example Screenshot](docs/guide/banner.png)
2728

docs/.vuepress/config.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ export default defineConfig({
131131
'types/label',
132132
'types/line',
133133
'types/point',
134-
'types/polygon'
134+
'types/polygon',
135+
'types/doughnutLabel'
135136
]
136137
},
137138
'developers',
@@ -220,6 +221,16 @@ export default defineConfig({
220221
'polygon/shadow'
221222
]
222223
},
224+
{
225+
title: 'Doughnut label annotations',
226+
children: [
227+
'doughnutLabel/basic',
228+
'doughnutLabel/canvas',
229+
'doughnutLabel/image',
230+
'doughnutLabel/gauge',
231+
'doughnutLabel/background',
232+
]
233+
},
223234
{
224235
title: 'Charts',
225236
children: [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<mxfile host="Electron" modified="2023-01-04T15:27:51.065Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.6.2 Chrome/106.0.5249.199 Electron/21.3.3 Safari/537.36" etag="UwpRt7ZZ2I8QNyQM25Nf" version="20.6.2" type="device"><diagram id="EVLCtf8sz0nmjKRDlPg8" name="Page-1">7ZfZjpswFIafhstUYLMkl4VZoqqVKkXVtFeVJzhg1XCocRqSp68NJonjjKaVMotGw03w7+Pt+31s4uGs6m4FacovkFPuIT/vPHzlIRT401j9aGU7KNNgOgiFYLkJOggLtqNjS6OuWU5bK1ACcMkaW1xCXdOltDQiBGzssBVwe9SGFNQRFkvCXfWO5bI0q0DJQZ9TVpTjyEE8G2oqMgablbQlyWFzJOFrD2cCQA5vVZdRruGNXIZ2Nw/U7icmaC3/pUF6t5vHP3dh1szR76+Lifz86dvE9PKH8LVZsJms3I4EBKzrnOpOfA+nm5JJumjIUtdulOdKK2XFVSlQr+6kxhGokLQ7kswkbylUVIqtCjG1yDfAzI5BoSlvDvxxbLTyiP2+ITGeF/u+D1jUiyHzH5TQ45RUL2pL0scJkbYZ9umKdZpqumKcZ8BB9B3h4bkMSpwkHyILJsZ75Qhn5MKMnggldlB2Hsq2Dk+1QmmDE7RlO3LfB+idSNYS2uG86LlyVtTqfalwUcUy1ZiYSuSPpqJiea4bpw2wWvbrilIvujqxoIZaB7VSwC96ItqpsIJamgMLhbqJ8pzVRQpSQqXE8DImBslJPvhuPkRn0iF8qmwIHQsH5t+Vkfok7gs/3h19+ISbnTg6O5eUwew5TY3cvEQ6Md2T7t3H0ccI2z6GZ26q5DlNjB0Th5m8GgvV/XbTP6/KRxzal+T+k+2lfEwcH82wb9lIAZJIBnoSk5l/obsztjMUn3F2ehlnVfHwLd/XHf0jwtd/AQ==</diagram></mxfile>

docs/guide/configuration.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ const options = {
5656
| Name | Option | Value
5757
| ---- | ---- | ----
5858
| `numbers` | `properties` | `['x', 'y', 'x2', 'y2', 'width', 'height', 'centerX', 'centerY', 'pointX', 'pointY', 'radius']`
59-
| `numbers` | `type` | `number`
59+
| `numbers` | `type` | `'number'`
60+
| `colors` | `properties` | `['backgroundColor', 'borderColor']`
61+
| `colors` | `type` | `'color'`
6062

6163
## Common
6264

docs/guide/index.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ This plugin needs to be registered. It does not function as inline plugin.
88

99
An annotation plugin for Chart.js >= 4.0.0
1010

11-
This plugin draws lines, boxes, labels, points, polygons and ellipses on the chart area. Annotations work with line, bar, scatter and bubble charts that use linear, logarithmic, time, or category scales. Annotations will not work on any chart that does not have exactly two axes, including pie, radar, and polar area charts.
11+
This plugin draws lines, boxes, labels, points, polygons and ellipses on the chart area. Annotations work with line, bar, scatter and bubble charts that use linear, logarithmic, time, or category scales.
12+
13+
Furthermore you can use a doughnut label annotation which can be used to add contents (text, image, canvas) in the middle area of the doughnut charts.
14+
15+
Annotations will not work on any chart that does not have exactly two axes, including pie, radar, and polar area charts.
1216

1317
![Banner](./banner.png)
1418

docs/guide/types/doughnutLabel.md

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# Doughnut Label Annotations
2+
3+
Doughnut label annotations are used to add contents (text, image, canvas) in the middle area of the doughnut charts.
4+
5+
```js chart-editor
6+
/* <block:options:0> */
7+
const options = {
8+
plugins: {
9+
annotation: {
10+
annotations: {
11+
dLabel: {
12+
type: 'doughnutLabel',
13+
content: ({chart}) => ['Total',
14+
chart.getDatasetMeta(0).total,
15+
'last 7 months'
16+
],
17+
font: [{size: 60}, {size: 50}, {size: 30}],
18+
color: ['black', 'red', 'grey']
19+
}
20+
}
21+
}
22+
}
23+
};
24+
/* </block:options> */
25+
26+
/* <block:config:1> */
27+
const config = {
28+
type: 'doughnut',
29+
data: {
30+
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
31+
datasets: [{
32+
label: 'Amount',
33+
data: [65, 59, 80, 81, 56, 55, 40]
34+
}]
35+
},
36+
options
37+
};
38+
/* </block:config> */
39+
40+
module.exports = {
41+
config
42+
};
43+
```
44+
45+
## Configuration
46+
47+
### Options
48+
49+
The following options are available for label annotations.
50+
51+
| Name | Type | [Scriptable](../options.md#scriptable-options) | Default
52+
| ---- | ---- | :----: | ----
53+
| [`autoHide`](#general) | `boolean` | Yes | `true`
54+
| [`autoFit`](#general) | `boolean` | Yes | `true`
55+
| [`backgroundColor`](#styling) | [`Color`](../options.md#color) | Yes | `'transparent'`
56+
| [`backgroundShadowColor`](#styling) | [`Color`](../options.md#color) | Yes | `'transparent'`
57+
| [`borderColor`](#styling) | [`Color`](../options.md#color) | Yes | `'transparent'`
58+
| [`borderDash`](#styling) | `number[]` | Yes | `[]`
59+
| [`borderDashOffset`](#styling) | `number` | Yes | `0`
60+
| [`borderShadowColor`](#styling) | [`Color`](../options.md#color) | Yes | `'transparent'`
61+
| [`display`](#general) | `boolean` | Yes | `true`
62+
| [`drawTime`](#general) | `string` | Yes | `'afterDatasetsDraw'`
63+
| [`borderJoinStyle`](#styling) | `string` | Yes | `'miter'`
64+
| [`borderWidth`](#styling) | `number`| Yes | `0`
65+
| [`color`](#styling) | [`Color`\|`Color[]`](../options.md#color) | Yes | `'black'`
66+
| [`content`](#general) | `string`\|`string[]`\|[`Image`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image)\|[`HTMLCanvasElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement) | Yes | `null`
67+
| [`font`](#styling) | [`Font`\|`Font[]`](../options.md#font) | Yes | `{}`
68+
| [`height`](#general) | `number`\|`string` | Yes | `undefined`
69+
| [`hitTolerance`](#general) | `number` | Yes | `0`
70+
| [`id`](#general) | `string` | No | `undefined`
71+
| [`init`](../configuration.html#common) | `boolean` | [See initial animation](../configuration.html#initial-animation) | `undefined`
72+
| [`opacity`](#styling) | `number` | Yes | `undefined`
73+
| [`position`](#position) | `string`\|`{x: string, y: string}` | Yes | `'center'`
74+
| [`rotation`](#general) | `number`| Yes | `0`
75+
| [`shadowBlur`](#styling) | `number` | Yes | `0`
76+
| [`shadowOffsetX`](#styling) | `number` | Yes | `0`
77+
| [`shadowOffsetY`](#styling) | `number` | Yes | `0`
78+
| [`spacing`](#general) | `number`| Yes | `1`
79+
| [`textAlign`](#general) | `string` | Yes | `'center'`
80+
| [`textStrokeColor`](#styling) | [`Color`](../options.md#color) | Yes | `undefined`
81+
| [`textStrokeWidth`](#styling) | `number` | Yes | `0`
82+
| [`width`](#general) | `number`\|`string` | Yes | `undefined`
83+
| [`xAdjust`](#general) | `number` | Yes | `0`
84+
| [`yAdjust`](#general) | `number` | Yes | `0`
85+
86+
### General
87+
88+
The content will be rendered in the center of the chart.
89+
90+
| Name | Description
91+
| ---- | ----
92+
| `autoFit` | If `true`, the label will be automatically fit inside the chart if its dimension is bigger than the available space.
93+
| `autoHide` | If `true`, the label will be automatically hidden if the dataset or its data items will be all hidden.
94+
| `content` | The content to show in the annotation.
95+
| `display` | Whether or not this annotation is visible.
96+
| `drawTime` | See [drawTime](../options.md#draw-time).
97+
| `height` | Overrides the height of the image or canvas element. Could be set in pixel by a number, or in percentage of current height of image or canvas element by a string. If undefined, uses the height of the image or canvas element. It is used only when the content is an image or canvas element.
98+
| `hitTolerance` | Amount of pixels to interact with annotations within some distance of the mouse point.
99+
| `id` | Identifies a unique id for the annotation and it will be stored in the element context. When the annotations are defined by an object, the id is automatically set using the key used to store the annotations in the object. When the annotations are configured by an array, the id, passed by this option in the annotation, will be used.
100+
| `rotation` | Rotation of the label in degrees.
101+
| `spacing` | The space in pixels between the inner radius of the chart and the background of the label.
102+
| `textAlign` | Text alignment of label content when there's more than one line. Possible options are: `'left'`, `'start'`, `'center'`, `'end'`, `'right'`.
103+
| `width` | Overrides the width of the image or canvas element. Could be set in pixel by a number, or in percentage of current width of image or canvas element by a string. If undefined, uses the width of the image or canvas element. It is used only when the content is an image or canvas element.
104+
| `xAdjust` | Adjustment of label relative to computed position. Negative values move the label left, positive right.
105+
| `yAdjust` | Adjustment along y-axis (top-bottom) of label relative to computed position. Negative values move the label up, positive down.
106+
107+
### Styling
108+
109+
| Name | Description
110+
| ---- | ----
111+
| `backgroundColor` | Fill color.
112+
| `backgroundShadowColor` | The color of shadow. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowColor).
113+
| `borderColor` | Stroke color.
114+
| `borderDash` | Length and spacing of dashes. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash).
115+
| `borderDashOffset` | Offset for border line dashes. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset).
116+
| `borderJoinStyle` | Border line join style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin).
117+
| `borderShadowColor` | The color of the border shadow. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowColor).
118+
| `borderWidth` | Stroke width (in pixels).
119+
| `color` | Text color. When the label to draw has multiple lines, you can use different color for each row of the label. This is enabled configuring an array of colors. When the lines are more than the configured colors, the last configuration of this option is used for all remaining lines.
120+
| `font` | Text font. When the label to draw has multiple lines, you can use different font for each row of the label. This is enabled configuring an array of fonts. When the lines are more than the configured fonts, the last configuration of this option is used for all remaining lines.
121+
| `opacity` | Overrides the opacity of the image or canvas element. Could be set a number in the range 0.0 to 1.0, inclusive. If undefined, uses the opacity of the image or canvas element. It is used only when the content is an image or canvas element.
122+
| `shadowBlur` | The amount of blur applied to shadow of the box where the label is located. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowBlur).
123+
| `shadowOffsetX` | The distance that shadow, of the box where the label is located, will be offset horizontally. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowOffsetX).
124+
| `shadowOffsetY` | The distance that shadow, of the box where the label is located, will be offset vertically. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowOffsetY).
125+
| `textStrokeColor` | The color of the stroke around the text.
126+
| `textStrokeWidth` | Stroke width around the text.
127+
128+
### Position
129+
130+
A position can be set in 2 different values types:
131+
132+
1. `'start'`, `'center'`, `'end'` which are defining where the label will be located
133+
2. a `string`, in percentage format `'number%'`, is representing the percentage on the size where the label will be located
134+
135+
If this value is a string (possible options are `'start'`, `'center'`, `'end'` or a string in percentage format), it is applied to vertical and horizontal position in the box.
136+
137+
If this value is an object, the `x` property defines the horizontal alignment in the label, with respect to the center point of the chart. Similarly, the `y` property defines the vertical alignment in the label, with respect to the center point of the chart. Possible options for both properties are `'start'`, `'center'`, `'end'`, a string in percentage format. Omitted property have value of the default, `'center'`.
138+
139+
#### borderRadius
140+
141+
If this value is a number, it is applied to all corners of the rectangle (topLeft, topRight, bottomLeft, bottomRight). If this value is an object, the `topLeft` property defines the top-left corners border radius. Similarly, the `topRight`, `bottomLeft`, and `bottomRight` properties can also be specified. Omitted corners have radius of 0.
142+
143+
## Element
144+
145+
The following diagram is showing the element properties about a `'doughnutLabel'` annotation:
146+
147+
![label](../../img/elementDoughnutLabelProps.png)
10.2 KB
Loading
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Filling background
2+
3+
```js chart-editor
4+
// <block:setup:2>
5+
const DATA_COUNT = 6;
6+
const MIN = 0;
7+
const MAX = 100;
8+
9+
const numberCfg = {count: DATA_COUNT, min: MIN, max: MAX, decimals: 0};
10+
11+
const data = {
12+
labels: ['Apples', 'Orange', 'Lime', 'Grapes', 'Apricots', 'Blackberries'],
13+
datasets: [{
14+
data: Utils.numbers(numberCfg)
15+
}]
16+
};
17+
// </block:setup>
18+
19+
// <block:annotation:1>
20+
const annotation = {
21+
type: 'doughnutLabel',
22+
content: ({chart}) => [chart.getDatasetMeta(0).total,
23+
'pieces of fruits'
24+
],
25+
font: [{size: 48}, {size: 20}],
26+
color: ['indigo', 'grey'],
27+
backgroundColor: 'rgba(0, 0, 0, 0.1)',
28+
borderColor: 'black',
29+
borderWidth: 2,
30+
borderDash: [7, 7],
31+
spacing: 2
32+
};
33+
// </block:annotation>
34+
35+
/* <block:config:0> */
36+
const config = {
37+
type: 'doughnut',
38+
data,
39+
options: {
40+
aspectRatio: 2,
41+
plugins: {
42+
annotation: {
43+
annotations: {
44+
annotation
45+
}
46+
}
47+
}
48+
}
49+
};
50+
/* </block:config> */
51+
52+
const actions = [
53+
{
54+
name: 'Randomize',
55+
handler: function(chart) {
56+
chart.data.datasets.forEach(function(dataset, i) {
57+
dataset.data = dataset.data.map(() => Utils.rand(MIN, MAX).toFixed(0));
58+
});
59+
chart.update();
60+
}
61+
}
62+
];
63+
64+
module.exports = {
65+
actions: actions,
66+
config: config,
67+
};
68+
```

docs/samples/doughnutLabel/basic.md

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Basic
2+
3+
```js chart-editor
4+
// <block:setup:3>
5+
const DATA_COUNT = 12;
6+
const MIN = 0;
7+
const MAX = 100;
8+
9+
const numberCfg = {count: DATA_COUNT, min: MIN, max: MAX, decimals: 0};
10+
11+
const data = {
12+
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
13+
datasets: [{
14+
data: Utils.numbers(numberCfg)
15+
}]
16+
};
17+
// </block:setup>
18+
19+
// <block:annotation:1>
20+
const annotation = {
21+
type: 'doughnutLabel',
22+
content: ({chart}) => ['Average',
23+
average(chart).toFixed(2),
24+
'on last ' + chart.data.labels.length + ' months'
25+
],
26+
font: [{size: 60}, {size: 50}, {size: 30}],
27+
color: ['black', 'red', 'grey']
28+
};
29+
// </block:annotation>
30+
31+
/* <block:config:0> */
32+
const config = {
33+
type: 'doughnut',
34+
data,
35+
options: {
36+
aspectRatio: 2,
37+
plugins: {
38+
annotation: {
39+
annotations: {
40+
annotation
41+
}
42+
}
43+
}
44+
}
45+
};
46+
/* </block:config> */
47+
48+
// <block:utils:2>
49+
function average(chart) {
50+
const values = chart.data.datasets[0].data;
51+
return values.reduce((a, b) => a + b, 0) / values.length;
52+
}
53+
// </block:utils>
54+
55+
const actions = [
56+
{
57+
name: 'Randomize',
58+
handler: function(chart) {
59+
chart.data.datasets.forEach(function(dataset, i) {
60+
dataset.data = dataset.data.map(() => Utils.rand(MIN, MAX));
61+
});
62+
chart.update();
63+
}
64+
}
65+
];
66+
67+
module.exports = {
68+
actions: actions,
69+
config: config,
70+
};
71+
```

0 commit comments

Comments
 (0)