Skip to content

Commit 1c2f66a

Browse files
igorlukanindangreenLeeLenaleee
authored
Introduce Colors plugin (#10764)
Introduces a colors plugin that provides a color palette Co-authored-by: Dan Onoshko <[email protected]> Co-authored-by: Jacco van den Berg <[email protected]>
1 parent 005aa45 commit 1c2f66a

File tree

21 files changed

+467
-38
lines changed

21 files changed

+467
-38
lines changed
762 Bytes
Loading

docs/general/colors.md

Lines changed: 123 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,142 @@
11
# Colors
22

3-
When supplying colors to Chart options, you can use a number of formats. You can specify the color as a string in hexadecimal, RGB, or HSL notations. If a color is needed, but not specified, Chart.js will use the global default color. There are 3 color options, stored at `Chart.defaults`, to set:
3+
Charts support three color options:
4+
* for geometric elements, you can change *background* and *border* colors;
5+
* for textual elements, you can change the *font* color.
46

5-
| Name | Type | Default | Description
6-
| ---- | ---- | ------- | -----------
7-
| `backgroundColor` | `Color` | `rgba(0, 0, 0, 0.1)` | Background color.
8-
| `borderColor` | `Color` | `rgba(0, 0, 0, 0.1)` | Border color.
9-
| `color` | `Color` | `#666` | Font color.
7+
Also, you can change the whole [canvas background](.../configuration/canvas-background.html).
108

11-
You can also pass a [CanvasGradient](https://developer.mozilla.org/en-US/docs/Web/API/CanvasGradient) object. You will need to create this before passing to the chart, but using it you can achieve some interesting effects.
9+
## Default colors
1210

13-
## Patterns and Gradients
11+
If a color is not specified, a global default color from `Chart.defaults` is used:
12+
13+
| Name | Type | Description | Default value
14+
| ---- | ---- | ----------- | -------------
15+
| `backgroundColor` | [`Color`](../api/#color) | Background color | `rgba(0, 0, 0, 0.1)`
16+
| `borderColor` | [`Color`](../api/#color) | Border color | `rgba(0, 0, 0, 0.1)`
17+
| `color` | [`Color`](../api/#color) | Font color | `#666`
18+
19+
You can reset default colors by updating these properties of `Chart.defaults`:
20+
21+
```javascript
22+
Chart.defaults.backgroundColor = '#9BD0F5';
23+
Chart.defaults.borderColor = '#36A2EB';
24+
Chart.defaults.color = '#000';
25+
```
26+
27+
### Per-dataset color settings
28+
29+
If your chart has multiple datasets, using default colors would make individual datasets indistiguishable. In that case, you can set `backgroundColor` and `borderColor` for each dataset:
30+
31+
```javascript
32+
const data = {
33+
labels: ['A', 'B', 'C'],
34+
datasets: [
35+
{
36+
label: 'Dataset 1',
37+
data: [1, 2, 3],
38+
borderColor: '#36A2EB',
39+
backgroundColor: '#9BD0F5',
40+
},
41+
{
42+
label: 'Dataset 2',
43+
data: [2, 3, 4],
44+
borderColor: '#FF6384',
45+
backgroundColor: '#FFB1C1',
46+
}
47+
]
48+
};
49+
```
50+
51+
However, setting colors for each dataset might require additional work that you'd rather not do. In that case, consider using the following plugins with pre-defined or generated palettes.
52+
53+
### Default color palette
54+
55+
If you don't have any preference for colors, you can use the built-in `Colors` plugin. It will cycle through a palette of seven Chart.js brand colors:
56+
57+
<div style="max-width: 500px;">
58+
59+
![Colors plugin palette](./colors-plugin-palette.png)
60+
61+
</div>
62+
63+
All you need is to import and register the plugin:
1464

15-
An alternative option is to pass a [CanvasPattern](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern) or [CanvasGradient](https://developer.mozilla.org/en/docs/Web/API/CanvasGradient) object instead of a string colour.
65+
```javascript
66+
import { Colors } from 'chart.js';
67+
68+
Chart.register(Colors);
69+
```
70+
71+
:::tip Note
72+
73+
If you are using the UMD version of Chart.js, this plugin will be enabled by default. You can disable it by setting the `enabled` option to `false`:
74+
75+
```js
76+
const options = {
77+
plugins: {
78+
colors: {
79+
enabled: false
80+
}
81+
}
82+
};
83+
```
84+
85+
:::
86+
87+
### Advanced color palettes
1688

17-
For example, if you wanted to fill a dataset with a pattern from an image you could do the following.
89+
See the [awesome list](https://github.com/chartjs/awesome#plugins) for plugins that would give you more flexibility defining color palettes.
90+
91+
## Color formats
92+
93+
You can specify the color as a string in either of the following notations:
94+
95+
| Notation | Example | Example with transparency
96+
| -------- | ------- | -------------------------
97+
| [Hexademical](https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color) | `#36A2EB` | `#36A2EB80`
98+
| [RGB](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb) or [RGBA](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgba) | `rgb(54, 162, 235)` | `rgba(54, 162, 235, 0.5)`
99+
| [HSL](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl) or [HSLA](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsla) | `hsl(204, 82%, 57%)` | `hsla(204, 82%, 57%, 0.5)`
100+
101+
Alternatively, you can pass a [CanvasPattern](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern) or [CanvasGradient](https://developer.mozilla.org/en/docs/Web/API/CanvasGradient) object instead of a string color to achieve some interesting effects.
102+
103+
## Patterns and Gradients
104+
105+
For example, you can fill a dataset with a pattern from an image.
18106

19107
```javascript
20108
const img = new Image();
21109
img.src = 'https://example.com/my_image.png';
22-
img.onload = function() {
23-
const ctx = document.getElementById('canvas').getContext('2d');
24-
const fillPattern = ctx.createPattern(img, 'repeat');
25-
26-
const chart = new Chart(ctx, {
27-
data: {
28-
labels: ['Item 1', 'Item 2', 'Item 3'],
29-
datasets: [{
30-
data: [10, 20, 30],
31-
backgroundColor: fillPattern
32-
}]
33-
}
34-
});
110+
img.onload = () => {
111+
const ctx = document.getElementById('canvas').getContext('2d');
112+
const fillPattern = ctx.createPattern(img, 'repeat');
113+
114+
const chart = new Chart(ctx, {
115+
data: {
116+
labels: ['Item 1', 'Item 2', 'Item 3'],
117+
datasets: [{
118+
data: [10, 20, 30],
119+
backgroundColor: fillPattern
120+
}]
121+
}
122+
});
35123
};
36124
```
125+
Pattern fills can help viewers with vision deficiencies (e.g., color-blindness or partial sight) [more easily understand your data](http://betweentwobrackets.com/data-graphics-and-colour-vision/).
37126

38-
Using pattern fills for data graphics can help viewers with vision deficiencies (e.g. color-blindness or partial sight) to [more easily understand your data](http://betweentwobrackets.com/data-graphics-and-colour-vision/).
39-
40-
Using the [Patternomaly](https://github.com/ashiguruma/patternomaly) library you can generate patterns to fill datasets.
127+
You can use the [Patternomaly](https://github.com/ashiguruma/patternomaly) library to generate patterns to fill datasets:
41128

42129
```javascript
43130
const chartData = {
44-
datasets: [{
45-
data: [45, 25, 20, 10],
46-
backgroundColor: [
47-
pattern.draw('square', '#ff6384'),
48-
pattern.draw('circle', '#36a2eb'),
49-
pattern.draw('diamond', '#cc65fe'),
50-
pattern.draw('triangle', '#ffce56')
51-
]
52-
}],
53-
labels: ['Red', 'Blue', 'Purple', 'Yellow']
131+
datasets: [{
132+
data: [45, 25, 20, 10],
133+
backgroundColor: [
134+
pattern.draw('square', '#ff6384'),
135+
pattern.draw('circle', '#36a2eb'),
136+
pattern.draw('diamond', '#cc65fe'),
137+
pattern.draw('triangle', '#ffce56')
138+
]
139+
}],
140+
labels: ['Red', 'Blue', 'Purple', 'Yellow']
54141
};
55142
```

src/plugins/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export {default as Colors} from './plugin.colors';
12
export {default as Decimation} from './plugin.decimation';
23
export {default as Filler} from './plugin.filler';
34
export {default as Legend} from './plugin.legend';

src/plugins/plugin.colors.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import type {Chart, ChartDataset} from '../types';
2+
3+
export interface ColorsPluginOptions {
4+
enabled?: boolean;
5+
}
6+
7+
type DatasetColorizer = (dataset: ChartDataset, i: number) => void;
8+
9+
interface ColorsDescriptor {
10+
backgroundColor?: unknown;
11+
borderColor?: unknown;
12+
}
13+
14+
const BORDER_COLORS = [
15+
'rgb(54, 162, 235)', // blue
16+
'rgb(255, 99, 132)', // red
17+
'rgb(255, 159, 64)', // orange
18+
'rgb(255, 205, 86)', // yellow
19+
'rgb(75, 192, 192)', // green
20+
'rgb(153, 102, 255)', // purple
21+
'rgb(201, 203, 207)' // grey
22+
];
23+
24+
// Border colors with 50% transparency
25+
const BACKGROUND_COLORS = /* #__PURE__ */ BORDER_COLORS.map(color => color.replace('rgb(', 'rgba(').replace(')', ', 0.5)'));
26+
27+
function getBorderColor(i: number) {
28+
return BORDER_COLORS[i % BORDER_COLORS.length];
29+
}
30+
31+
function getBackgroundColor(i: number) {
32+
return BACKGROUND_COLORS[i % BACKGROUND_COLORS.length];
33+
}
34+
35+
function createDefaultDatasetColorizer() {
36+
return (dataset: ChartDataset, i: number) => {
37+
dataset.borderColor = getBorderColor(i);
38+
dataset.backgroundColor = getBackgroundColor(i);
39+
};
40+
}
41+
42+
function createDoughnutDatasetColorizer() {
43+
let i = 0;
44+
45+
return (dataset: ChartDataset) => {
46+
dataset.backgroundColor = dataset.data.map(() => getBorderColor(i++));
47+
};
48+
}
49+
50+
function createPolarAreaDatasetColorizer() {
51+
let i = 0;
52+
53+
return (dataset: ChartDataset) => {
54+
dataset.backgroundColor = dataset.data.map(() => getBackgroundColor(i++));
55+
};
56+
}
57+
58+
function containsColorsDefinitions(
59+
descriptors: ColorsDescriptor[] | Record<string, ColorsDescriptor>
60+
) {
61+
let k: number | string;
62+
63+
for (k in descriptors) {
64+
if (descriptors[k].borderColor || descriptors[k].backgroundColor) {
65+
return true;
66+
}
67+
}
68+
69+
return false;
70+
}
71+
72+
export default {
73+
id: 'colors',
74+
75+
defaults: {
76+
enabled: true,
77+
},
78+
79+
beforeLayout(chart: Chart, _args, options: ColorsPluginOptions) {
80+
if (!options.enabled) {
81+
return;
82+
}
83+
84+
const {
85+
type,
86+
options: {elements},
87+
data: {datasets}
88+
} = chart.config;
89+
90+
if (containsColorsDefinitions(datasets) || elements && containsColorsDefinitions(elements)) {
91+
return;
92+
}
93+
94+
let colorizer: DatasetColorizer;
95+
96+
if (type === 'doughnut') {
97+
colorizer = createDoughnutDatasetColorizer();
98+
} else if (type === 'polarArea') {
99+
colorizer = createPolarAreaDatasetColorizer();
100+
} else {
101+
colorizer = createDefaultDatasetColorizer();
102+
}
103+
104+
datasets.forEach(colorizer);
105+
}
106+
};

test/fixtures/plugin.colors/bar.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module.exports = {
2+
config: {
3+
type: 'bar',
4+
data: {
5+
labels: [0, 1, 2, 3, 4, 5],
6+
datasets: [
7+
{
8+
data: [0, 5, 10, null, -10, -5],
9+
},
10+
{
11+
data: [10, 2, 3, null, 10, 5]
12+
}
13+
]
14+
},
15+
options: {
16+
scales: {
17+
x: {
18+
ticks: {
19+
display: false,
20+
}
21+
},
22+
y: {
23+
ticks: {
24+
display: false,
25+
}
26+
}
27+
},
28+
plugins: {
29+
legend: false,
30+
colors: {
31+
enabled: true
32+
}
33+
}
34+
}
35+
}
36+
};
15.4 KB
Loading
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
module.exports = {
2+
config: {
3+
type: 'bubble',
4+
data: {
5+
datasets: [{
6+
data: [{x: 12, y: 54, r: 22.4}]
7+
}, {
8+
data: [{x: 18, y: 38, r: 25}]
9+
}]
10+
},
11+
options: {
12+
scales: {
13+
x: {
14+
ticks: {
15+
display: false,
16+
}
17+
},
18+
y: {
19+
ticks: {
20+
display: false,
21+
}
22+
}
23+
},
24+
plugins: {
25+
legend: false,
26+
colors: {
27+
enabled: true
28+
}
29+
}
30+
}
31+
}
32+
};
16.4 KB
Loading
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module.exports = {
2+
config: {
3+
type: 'doughnut',
4+
data: {
5+
datasets: [
6+
{
7+
data: [0, 2, 4, null, 6, 8]
8+
},
9+
{
10+
data: [5, 1, 6, 2, null, 9]
11+
}
12+
]
13+
},
14+
options: {
15+
plugins: {
16+
legend: false,
17+
colors: {
18+
enabled: true
19+
}
20+
}
21+
}
22+
}
23+
};
49.9 KB
Loading

0 commit comments

Comments
 (0)