Skip to content

Commit e1347fc

Browse files
committed
Implement multiple labels per data element
1 parent 9bd22fa commit e1347fc

30 files changed

Lines changed: 971 additions & 79 deletions

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Requires [Chart.js](https://github.com/chartjs/Chart.js/releases) **2.7.0** or l
2020
- [Introduction](https://chartjs-plugin-datalabels.netlify.com/guide/)
2121
- [Getting Started](https://chartjs-plugin-datalabels.netlify.com/guide/getting-started.html)
2222
- [Options](https://chartjs-plugin-datalabels.netlify.com/guide/options.html)
23+
- [Labels](https://chartjs-plugin-datalabels.netlify.com/guide/labels.html)
2324
- [Positioning](https://chartjs-plugin-datalabels.netlify.com/guide/positioning.html)
2425
- [Formatting](https://chartjs-plugin-datalabels.netlify.com/guide/formatting.html)
2526
- [Events](https://chartjs-plugin-datalabels.netlify.com/guide/events.html)

docs/.vuepress/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module.exports = {
2424
'/guide/',
2525
'/guide/getting-started',
2626
'/guide/options',
27+
'/guide/labels',
2728
'/guide/positioning',
2829
'/guide/formatting',
2930
'/guide/events'

docs/guide/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This plugin doesn't provide any public API (except the plugin options), thus you
1414

1515
* [Getting Started](getting-started.md)
1616
* [Options](options.md)
17+
* [Labels](labels.md)
1718
* [Positioning](positioning.md)
1819
* [Formating](formatting.md)
1920
* [Events](events.md)

docs/guide/events.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ This plugin currently supports the following label events:
1414

1515
## Listeners
1616

17-
The `listeners` option allows to register callbacks to be notified when an event is detected on a specific label. This option is an object where the property is the type of the event to listen and the value is a callback with a unique `context` argument.
17+
The `listeners` option allows to register callbacks to be notified when an event is detected on a specific label. This option is an object where each property represents an event, the key being the type of the event to listen and the value being a callback accepting a unique `context` argument.
1818

1919
The `context` contains the same information as for [scriptable options](options.md#option-context), can be modified (e.g. add new properties) and thus, **if the callback explicitly returns `true`**, the label is updated with the new context and the chart re-rendered. This allows to implement visual interactions with labels such as highlight, selection, etc.
2020

docs/guide/labels.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# Labels
2+
3+
By default, a single label is created per data, however, it's possible to define multiple labels for each data element using the `labels` options. This option is an object where each property represents a new label, the key being the label key and the value being the options specific to each label. These options are merged on top of the options defined at the chart **and** dataset levels.
4+
5+
## Multiple Labels
6+
7+
The following snippet creates two labels for every data element, the first with `title` as key and the second with `value` as key. The `title` label text is blue with font in bold. The `value` label text is green with normal font.
8+
9+
```js
10+
{
11+
options: {
12+
plugins: {
13+
datalabels: {
14+
color: 'blue',
15+
labels: {
16+
title: {
17+
font: {
18+
weight: 'bold'
19+
}
20+
},
21+
value: {
22+
color: 'green'
23+
}
24+
}
25+
}
26+
}
27+
}
28+
}
29+
```
30+
31+
## Dataset Overrides
32+
33+
While the previous example creates multiple labels with the same options for all datasets, it's possible to add, modify and remove labels for specific datasets by referring to the label key.
34+
35+
### Modifying Labels
36+
37+
To modify a label for a specific dataset, create an entry in the `labels` dataset options using the same key:
38+
39+
```js
40+
{
41+
data: {
42+
datasets: [{
43+
// First dataset.
44+
datalabels: {
45+
color: 'yellow'
46+
}
47+
}, {
48+
// Second dataset.
49+
datalabels: {
50+
labels: {
51+
title: {
52+
color: 'green'
53+
}
54+
}
55+
}
56+
}]
57+
},
58+
options: {
59+
plugins: {
60+
datalabels: {
61+
color: 'pink',
62+
labels: {
63+
value: {},
64+
title: {
65+
color: 'blue'
66+
}
67+
}
68+
}
69+
}
70+
}
71+
}
72+
```
73+
74+
This example creates for each data element in the *first* dataset:
75+
- a `value` label with text in yellow
76+
- a `title` label with text in blue
77+
78+
and for each data element in the *second* dataset:
79+
- a `value` label with text in pink
80+
- a `title` label with text in green
81+
82+
::: warning IMPORTANT
83+
Options defined under each `labels.<key>` always override options defined at the chart **and** dataset level (in the previous example, the `title` label text of the *first* dataset is blue, not yellow).
84+
:::
85+
86+
### Adding Label
87+
88+
To add a new label to a specific dataset, create an entry under the `labels` dataset options using a *inexistent* label key. The following example creates one label (`title`) for each data element in the *first* dataset and two labels (`title` and `value`) for each data element in the *second* dataset:
89+
90+
```js
91+
{
92+
data: {
93+
datasets: [{
94+
// First dataset.
95+
}, {
96+
// Second dataset.
97+
datalabels: {
98+
labels: {
99+
value: {
100+
color: 'green'
101+
}
102+
}
103+
}
104+
}]
105+
},
106+
options: {
107+
plugins: {
108+
datalabels: {
109+
labels: {
110+
title: {
111+
color: 'blue'
112+
}
113+
}
114+
}
115+
}
116+
}
117+
}
118+
```
119+
120+
### Removing Label
121+
122+
To remove a label for a specific dataset, create an `null` entry under the `labels` dataset options for the key of the label to remove. The following example removes the `title` label in the *second* dataset:
123+
124+
```js
125+
{
126+
data: {
127+
datasets: [{
128+
// First dataset.
129+
}, {
130+
// Second dataset.
131+
datalabels: {
132+
labels: {
133+
title: null
134+
}
135+
}
136+
}]
137+
},
138+
options: {
139+
plugins: {
140+
datalabels: {
141+
labels: {
142+
title: {
143+
color: 'blue'
144+
}
145+
}
146+
}
147+
}
148+
}
149+
}
150+
```

docs/guide/options.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ The following table lists all available options:
2121
| `font.weight` | `string` | - | - | `'normal'`
2222
| [`font.lineHeight`](formatting.md#multiline-labels) | `number` \| `string` | - | - | `1.2`
2323
| [`formatter`](formatting.md#data-transformation) | `function` \| `null` | - | - | -
24+
| [`labels`](labels.md) | `object` | - | - | `undefined`
2425
| [`listeners`](events.md) | `object` | - | - | `{}`
2526
| [`offset`](positioning.md#alignment-and-offset) | `number` | Yes | Yes | `4`
2627
| `opacity` | `number` | Yes | Yes | `1`
@@ -62,11 +63,13 @@ The option context is used to give contextual information when resolving options
6263

6364
The context object contains the following properties:
6465

65-
- `active` (bool): whether the associated element is hovered ([see interactions](http://www.chartjs.org/docs/latest/general/interactions/))
66-
- `chart` (Chart): the associated chart
67-
- `dataIndex` (int): index of the associated data
68-
- `dataset` (object): the dataset at index `datasetIndex`
69-
- `datasetIndex` (int): index of the associated dataset
66+
| Property | Type | Description
67+
| -------- | ---- | -----------
68+
| `active` | `bool` | Whether the associated element is hovered ([see interactions](http://www.chartjs.org/docs/latest/general/interactions/)).
69+
| `chart` | `Chart` | The associated chart.
70+
| `dataIndex` | `number` | The index of the associated data.
71+
| `dataset` | `object` | The dataset at index `datasetIndex`.
72+
| `datasetIndex` | `number` | The index of the associated dataset.
7073

7174
## Indexable Options
7275

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
<script>
2727
var SAMPLE_INFO = {
28-
group: 'Formatting',
28+
group: 'Advanced',
2929
name: 'Custom Labels',
3030
desc: 'This example displays the data labels instead ' +
3131
'of the data values, using a custom formatter'
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
<!DOCTYPE html>
2+
<html lang="en-US">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
6+
<meta name="viewport" content="width=device-width, initial-scale=1">
7+
<link rel="stylesheet" type="text/css" href="../style.css">
8+
<link rel="icon" type="image/ico" href="../favicon.ico">
9+
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.7.0/dist/Chart.min.js"></script>
10+
<script src="../../dist/chartjs-plugin-datalabels.js"></script>
11+
<script src="../utils.js"></script>
12+
</head>
13+
<body>
14+
<div id="side">
15+
<div id="header"></div>
16+
<div id="actions">
17+
<button onclick="randomize(this)">Randomize</button>
18+
</div>
19+
</div>
20+
21+
<div id="charts">
22+
<div class="wrapper"><canvas id="chart-0"></canvas></div>
23+
</div>
24+
25+
<script>
26+
var SAMPLE_INFO = {
27+
group: 'Advanced',
28+
name: 'Multiple Labels',
29+
desc: 'This example displays 3 labels per data, one for the '
30+
+ 'index, one for the label and one for the value. Move '
31+
+ 'the mouse over the chart to display label ids.'
32+
};
33+
</script>
34+
35+
<script id="script-init">
36+
var DATA_COUNT = 4;
37+
var labels = [
38+
'Earth',
39+
'Mars',
40+
'Saturn',
41+
'Jupiter'
42+
];
43+
44+
Samples.srand(4);
45+
46+
Chart.helpers.merge(Chart.defaults.global, {
47+
aspectRatio: 4 / 3,
48+
tooltips: false,
49+
layout: {
50+
padding: {
51+
top: 42,
52+
right: 16,
53+
bottom: 32,
54+
left: 8
55+
}
56+
},
57+
elements: {
58+
line: {
59+
fill: false
60+
},
61+
point: {
62+
hoverRadius: 7,
63+
radius: 5
64+
}
65+
},
66+
plugins: {
67+
legend: false,
68+
title: false
69+
}
70+
});
71+
</script>
72+
73+
<script id="script-construct">
74+
var chart = new Chart('chart-0', {
75+
type: 'doughnut',
76+
data: {
77+
labels: labels,
78+
datasets: [{
79+
backgroundColor: Samples.colors({
80+
color: Samples.color(1),
81+
mode: 'darken'
82+
}),
83+
hoverBorderColor: 'white',
84+
data: Samples.numbers({
85+
count: DATA_COUNT,
86+
min: 0,
87+
max: 100
88+
}),
89+
datalabels: {
90+
labels: {
91+
index: {
92+
align: 'end',
93+
anchor: 'end',
94+
color: function(ctx) {
95+
return ctx.dataset.backgroundColor;
96+
},
97+
font: {size: 18},
98+
formatter: function(value, ctx) {
99+
return ctx.active
100+
? 'index'
101+
: '#' + (ctx.dataIndex + 1);
102+
},
103+
offset: 8,
104+
opacity: function(ctx) {
105+
return ctx.active ? 1 : 0.5;
106+
}
107+
},
108+
name: {
109+
align: 'top',
110+
font: {size: 16},
111+
formatter: function(value, ctx) {
112+
return ctx.active
113+
? 'name'
114+
: ctx.chart.data.labels[ctx.dataIndex];
115+
}
116+
},
117+
value: {
118+
align: 'bottom',
119+
backgroundColor: function(ctx) {
120+
var value = ctx.dataset.data[ctx.dataIndex];
121+
return value > 50 ? 'white' : null;
122+
},
123+
borderColor: 'white',
124+
borderWidth: 2,
125+
borderRadius: 4,
126+
color: function(ctx) {
127+
var value = ctx.dataset.data[ctx.dataIndex];
128+
return value > 50
129+
? ctx.dataset.backgroundColor
130+
: 'white';
131+
},
132+
formatter: function(value, ctx) {
133+
return ctx.active
134+
? 'value'
135+
: Math.round(value * 1000) / 1000;
136+
},
137+
padding: 4
138+
}
139+
}
140+
}
141+
}]
142+
},
143+
options: {
144+
cutoutPercentage: 8,
145+
padding: 64,
146+
plugins: {
147+
datalabels: {
148+
color: 'white',
149+
display: function(ctx) {
150+
return ctx.dataset.data[ctx.dataIndex] > 10;
151+
},
152+
font: {weight: 'bold'},
153+
offset: 0,
154+
padding: 0
155+
}
156+
}
157+
}
158+
});
159+
</script>
160+
161+
<script id="script-actions">
162+
function randomize() {
163+
chart.data.datasets.forEach(function(dataset, i) {
164+
dataset.backgroundColor = Samples.colors({
165+
color: Samples.color(),
166+
mode: 'darken'
167+
});
168+
dataset.data = dataset.data.map(function(value) {
169+
return Samples.rand(0, 100);
170+
});
171+
});
172+
chart.update();
173+
}
174+
</script>
175+
</body>
176+
</html>

0 commit comments

Comments
 (0)