@ons/design-system 72.9.2 → 72.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/chart/_chart.scss +74 -1
- package/components/chart/_macro.njk +64 -5
- package/components/chart/_macro.spec.js +405 -0
- package/components/chart/bar-chart.js +2 -2
- package/components/chart/boxplot.js +37 -0
- package/components/chart/chart-constants.js +13 -0
- package/components/chart/chart.js +86 -46
- package/components/chart/columnrange-chart.js +94 -0
- package/components/chart/common-chart-options.js +28 -15
- package/components/chart/example-bar-chart-with-annotations.njk +1 -1
- package/components/chart/example-bar-chart-with-point-range-and-reference-line-annotations.njk +95 -0
- package/components/chart/example-bar-with-confidence-levels.njk +71 -0
- package/components/chart/example-clustered-column-chart.njk +1 -3
- package/components/chart/example-column-chart-with-annotations.njk +1 -1
- package/components/chart/example-column-chart-with-range-annotations.njk +64 -0
- package/components/chart/example-column-chart-with-reference-line-annotations.njk +64 -0
- package/components/chart/example-column-with-confidence-levels.njk +61 -0
- package/components/chart/example-line-chart-with-annotations.njk +3 -3
- package/components/chart/example-line-chart-with-markers.njk +1 -1
- package/components/chart/example-line-chart-with-range-annotations-inside.njk +238 -0
- package/components/chart/example-line-chart-with-range-annotations-outside-left-right.njk +240 -0
- package/components/chart/example-line-chart-with-range-annotations-outside-top-bottom.njk +239 -0
- package/components/chart/example-line-chart-with-reference-line-annotations.njk +236 -0
- package/components/chart/example-scatter-chart.njk +1 -1
- package/components/chart/range-annotations-options.js +216 -0
- package/components/chart/reference-line-annotations-options.js +93 -0
- package/components/chart/scatter-chart.js +15 -0
- package/components/chart/specific-chart-options.js +1 -1
- package/components/chart/utilities.js +96 -0
- package/css/main.css +1 -1
- package/package.json +1 -1
- package/scripts/main.es5.js +1 -1
- package/scripts/main.js +1 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import ChartConstants from './chart-constants';
|
|
2
|
+
import ColumnChart from './column-chart';
|
|
3
|
+
|
|
4
|
+
class Boxplot {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.constants = ChartConstants.constants();
|
|
7
|
+
this.columnChart = new ColumnChart();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
getBoxplotOptions = (config, useStackedLayout, extraLines) => {
|
|
11
|
+
return {
|
|
12
|
+
plotOptions: {
|
|
13
|
+
boxplot: {
|
|
14
|
+
...this.columnChart.getPointPadding(config, useStackedLayout, extraLines, false),
|
|
15
|
+
boxDashStyle: 'Solid',
|
|
16
|
+
fillColor: this.constants.uncertaintyRangeColor,
|
|
17
|
+
lineWidth: 0,
|
|
18
|
+
medianColor: this.constants.estimateLineColor,
|
|
19
|
+
medianDashStyle: 'Solid',
|
|
20
|
+
medianWidth: 3,
|
|
21
|
+
stemWidth: 0,
|
|
22
|
+
whiskerWidth: 0,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
legend: {
|
|
26
|
+
enabled: false, // Legend is handled via custom HTML for box plots, so we disable the default Highcharts legend
|
|
27
|
+
symbolRadius: 0,
|
|
28
|
+
itemStyle: {
|
|
29
|
+
fontSize: this.constants.defaultFontSize,
|
|
30
|
+
color: this.constants.legendLabelColor,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default Boxplot;
|
|
@@ -9,7 +9,10 @@ class ChartConstants {
|
|
|
9
9
|
categoryLabelColor: '#414042',
|
|
10
10
|
gridLineColor: '#d9d9d9',
|
|
11
11
|
zeroLineColor: '#b3b3b3',
|
|
12
|
+
estimateLineColor: '#003c57',
|
|
13
|
+
uncertaintyRangeColor: 'rgba(32, 96, 149, 0.65)',
|
|
12
14
|
defaultFontSize: '0.875rem', // 14px
|
|
15
|
+
shadingColor: '#ececec',
|
|
13
16
|
lineMarkerStyles: [
|
|
14
17
|
{
|
|
15
18
|
radius: 4,
|
|
@@ -93,6 +96,16 @@ class ChartConstants {
|
|
|
93
96
|
lineColor: '#ffffff',
|
|
94
97
|
},
|
|
95
98
|
],
|
|
99
|
+
confidenceLevelMarkerStyles: [
|
|
100
|
+
{
|
|
101
|
+
radius: 6,
|
|
102
|
+
symbol: 'diamond',
|
|
103
|
+
lineWidth: 2,
|
|
104
|
+
lineColor: '#222',
|
|
105
|
+
outline: true,
|
|
106
|
+
fillColor: 'white',
|
|
107
|
+
},
|
|
108
|
+
],
|
|
96
109
|
};
|
|
97
110
|
|
|
98
111
|
return constants;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Highcharts from 'highcharts';
|
|
2
2
|
import 'highcharts/modules/accessibility';
|
|
3
3
|
import 'highcharts/modules/annotations';
|
|
4
|
+
import 'highcharts/highcharts-more';
|
|
4
5
|
|
|
5
6
|
import CommonChartOptions from './common-chart-options';
|
|
6
7
|
import SpecificChartOptions from './specific-chart-options';
|
|
@@ -8,8 +9,13 @@ import LineChart from './line-chart';
|
|
|
8
9
|
import BarChart from './bar-chart';
|
|
9
10
|
import ColumnChart from './column-chart';
|
|
10
11
|
import ScatterChart from './scatter-chart';
|
|
12
|
+
import Boxplot from './boxplot';
|
|
11
13
|
import AnnotationsOptions from './annotations-options';
|
|
14
|
+
import RangeAnnotationsOptions from './range-annotations-options';
|
|
15
|
+
import ReferenceLineAnnotationsOptions from './reference-line-annotations-options';
|
|
16
|
+
import { preparePlotLinesAndBands, mergeConfigs } from './utilities';
|
|
12
17
|
import AreaChart from './area-chart';
|
|
18
|
+
import ColumnRangeChart from './columnrange-chart';
|
|
13
19
|
|
|
14
20
|
class HighchartsBaseChart {
|
|
15
21
|
static selector() {
|
|
@@ -29,8 +35,18 @@ class HighchartsBaseChart {
|
|
|
29
35
|
this.useStackedLayout = this.node.hasAttribute('data-highcharts-use-stacked-layout');
|
|
30
36
|
this.config = JSON.parse(this.node.querySelector(`[data-highcharts-config--${this.id}]`).textContent);
|
|
31
37
|
if (this.node.querySelector(`[data-highcharts-annotations--${this.id}]`)) {
|
|
32
|
-
|
|
33
|
-
this.annotationsOptions = new AnnotationsOptions(annotations);
|
|
38
|
+
this.annotations = JSON.parse(this.node.querySelector(`[data-highcharts-annotations--${this.id}]`).textContent);
|
|
39
|
+
this.annotationsOptions = new AnnotationsOptions(this.annotations);
|
|
40
|
+
}
|
|
41
|
+
if (this.node.querySelector(`[data-highcharts-range-annotations--${this.id}]`)) {
|
|
42
|
+
this.rangeAnnotations = JSON.parse(this.node.querySelector(`[data-highcharts-range-annotations--${this.id}]`).textContent);
|
|
43
|
+
this.rangeAnnotationsOptions = new RangeAnnotationsOptions(this.rangeAnnotations);
|
|
44
|
+
}
|
|
45
|
+
if (this.node.querySelector(`[data-highcharts-reference-line-annotations--${this.id}]`)) {
|
|
46
|
+
this.referenceLineAnnotations = JSON.parse(
|
|
47
|
+
this.node.querySelector(`[data-highcharts-reference-line-annotations--${this.id}]`).textContent,
|
|
48
|
+
);
|
|
49
|
+
this.referenceLineAnnotationsOptions = new ReferenceLineAnnotationsOptions(this.referenceLineAnnotations);
|
|
34
50
|
}
|
|
35
51
|
this.percentageHeightDesktop = this.node.dataset.highchartsPercentageHeightDesktop;
|
|
36
52
|
this.percentageHeightMobile = this.node.dataset.highchartsPercentageHeightMobile;
|
|
@@ -47,13 +63,18 @@ class HighchartsBaseChart {
|
|
|
47
63
|
? parseInt(this.node.dataset.highchartsYAxisTickIntervalDesktop)
|
|
48
64
|
: undefined;
|
|
49
65
|
this.commonChartOptions = new CommonChartOptions(this.xAxisTickIntervalDesktop, this.yAxisTickIntervalDesktop);
|
|
66
|
+
this.estimateLineLabel = this.node.dataset.highchartsEstimateLineLabel;
|
|
67
|
+
this.uncertainyRangeLabel = this.node.dataset.highchartsUncertaintyRangeLabel;
|
|
50
68
|
this.specificChartOptions = new SpecificChartOptions(this.theme, this.chartType, this.config);
|
|
51
69
|
this.lineChart = new LineChart();
|
|
52
70
|
this.barChart = new BarChart();
|
|
53
71
|
this.columnChart = new ColumnChart();
|
|
54
72
|
this.areaChart = new AreaChart();
|
|
55
73
|
this.scatterChart = new ScatterChart();
|
|
74
|
+
this.columnRangeChart = new ColumnRangeChart();
|
|
75
|
+
this.boxplot = new Boxplot();
|
|
56
76
|
this.extraLines = this.checkForExtraLines();
|
|
77
|
+
this.extraScatter = this.checkForExtraScatter();
|
|
57
78
|
if (window.isCommonChartOptionsDefined === undefined) {
|
|
58
79
|
this.setCommonChartOptions();
|
|
59
80
|
window.isCommonChartOptionsDefined = true;
|
|
@@ -62,6 +83,7 @@ class HighchartsBaseChart {
|
|
|
62
83
|
this.setSpecificChartOptions();
|
|
63
84
|
this.setResponsiveOptions();
|
|
64
85
|
this.setLoadEvent();
|
|
86
|
+
this.setRenderEvent();
|
|
65
87
|
this.setWindowResizeEvent();
|
|
66
88
|
this.chart = Highcharts.chart(chartNode, this.config);
|
|
67
89
|
}
|
|
@@ -71,83 +93,69 @@ class HighchartsBaseChart {
|
|
|
71
93
|
return this.chartType === 'line' ? 0 : this.config.series.filter((series) => series.type === 'line').length;
|
|
72
94
|
};
|
|
73
95
|
|
|
96
|
+
// Check for the number of extra line series in the config
|
|
97
|
+
checkForExtraScatter = () => {
|
|
98
|
+
return this.chartType === 'scatter' ? 0 : this.config.series.filter((series) => series.type === 'scatter').length;
|
|
99
|
+
};
|
|
100
|
+
|
|
74
101
|
// Set up the global Highcharts options which are used for all charts
|
|
75
102
|
setCommonChartOptions = () => {
|
|
76
103
|
const chartOptions = this.commonChartOptions.getOptions();
|
|
77
104
|
Highcharts.setOptions(chartOptions);
|
|
78
105
|
};
|
|
79
106
|
|
|
80
|
-
// Utility function to merge two configs together
|
|
81
|
-
mergeConfigs = (baseConfig, newConfig) => {
|
|
82
|
-
// If newConfig is null/undefined, return baseConfig
|
|
83
|
-
if (!newConfig) return baseConfig;
|
|
84
|
-
|
|
85
|
-
// Create a new object to store the merged result
|
|
86
|
-
const merged = { ...baseConfig };
|
|
87
|
-
|
|
88
|
-
// Iterate through all keys in newConfig
|
|
89
|
-
Object.keys(newConfig).forEach((key) => {
|
|
90
|
-
// Get values from both configs for this key
|
|
91
|
-
const baseValue = merged[key];
|
|
92
|
-
const newValue = newConfig[key];
|
|
93
|
-
|
|
94
|
-
// If both values are objects (and not null), recursively merge them
|
|
95
|
-
if (
|
|
96
|
-
baseValue &&
|
|
97
|
-
newValue &&
|
|
98
|
-
typeof baseValue === 'object' &&
|
|
99
|
-
typeof newValue === 'object' &&
|
|
100
|
-
!Array.isArray(baseValue) &&
|
|
101
|
-
!Array.isArray(newValue)
|
|
102
|
-
) {
|
|
103
|
-
merged[key] = this.mergeConfigs(baseValue, newValue);
|
|
104
|
-
} else {
|
|
105
|
-
// For non-objects and arrays use the new value
|
|
106
|
-
// If the new value is null/undefined, use the base value
|
|
107
|
-
merged[key] = newValue ?? baseValue;
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
return merged;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
107
|
// Set up options for specific charts and chart types
|
|
115
108
|
setSpecificChartOptions = () => {
|
|
116
109
|
const specificChartOptions = this.specificChartOptions.getOptions();
|
|
117
110
|
const lineChartOptions = this.lineChart.getLineChartOptions();
|
|
118
111
|
const barChartOptions = this.barChart.getBarChartOptions(this.useStackedLayout);
|
|
112
|
+
const columnRangeChartOptions = this.columnRangeChart.getColumnRangeChartOptions();
|
|
119
113
|
const columnChartOptions = this.columnChart.getColumnChartOptions(this.config, this.useStackedLayout, this.extraLines);
|
|
120
114
|
const areaChartOptions = this.areaChart.getAreaChartOptions();
|
|
121
115
|
const scatterChartOptions = this.scatterChart.getScatterChartOptions();
|
|
116
|
+
const boxplotOptions = this.boxplot.getBoxplotOptions(this.config, this.useStackedLayout, this.extraLines);
|
|
122
117
|
// Merge specificChartOptions with the existing config
|
|
123
|
-
this.config =
|
|
118
|
+
this.config = mergeConfigs(this.config, specificChartOptions);
|
|
124
119
|
|
|
125
120
|
if (this.chartType === 'line') {
|
|
126
121
|
// Merge the line chart options with the existing config
|
|
127
|
-
this.config =
|
|
122
|
+
this.config = mergeConfigs(this.config, lineChartOptions);
|
|
128
123
|
}
|
|
129
124
|
|
|
130
125
|
if (this.chartType === 'bar') {
|
|
131
126
|
// Merge the bar chart options with the existing config
|
|
132
|
-
this.config =
|
|
127
|
+
this.config = mergeConfigs(this.config, barChartOptions);
|
|
128
|
+
}
|
|
129
|
+
if (this.chartType === 'columnrange') {
|
|
130
|
+
// Merge the bar chart options with the existing config
|
|
131
|
+
this.config = mergeConfigs(this.config, columnRangeChartOptions);
|
|
133
132
|
}
|
|
134
133
|
if (this.chartType === 'column') {
|
|
135
134
|
// Merge the column chart options with the existing config
|
|
136
|
-
this.config =
|
|
135
|
+
this.config = mergeConfigs(this.config, columnChartOptions);
|
|
137
136
|
}
|
|
138
137
|
if (this.chartType === 'area') {
|
|
139
138
|
// Merge the area chart options with the existing config
|
|
140
|
-
this.config =
|
|
139
|
+
this.config = mergeConfigs(this.config, areaChartOptions);
|
|
141
140
|
}
|
|
142
141
|
if (this.chartType === 'scatter') {
|
|
143
142
|
// Merge the scatter chart options with the existing config
|
|
144
|
-
this.config =
|
|
143
|
+
this.config = mergeConfigs(this.config, scatterChartOptions);
|
|
144
|
+
}
|
|
145
|
+
if (this.chartType === 'boxplot') {
|
|
146
|
+
// Merge the boxplot chart options with the existing config
|
|
147
|
+
this.config = mergeConfigs(this.config, boxplotOptions);
|
|
145
148
|
}
|
|
146
149
|
|
|
147
150
|
if (this.extraLines > 0) {
|
|
148
|
-
this.config =
|
|
151
|
+
this.config = mergeConfigs(this.config, this.lineChart.getLineChartOptions());
|
|
149
152
|
if (this.chartType === 'column') {
|
|
150
|
-
this.config =
|
|
153
|
+
this.config = mergeConfigs(this.config, columnChartOptions);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (this.extraScatter > 0) {
|
|
157
|
+
if (this.chartType === 'columnrange') {
|
|
158
|
+
this.config = mergeConfigs(this.config, columnRangeChartOptions);
|
|
151
159
|
}
|
|
152
160
|
}
|
|
153
161
|
|
|
@@ -166,19 +174,28 @@ class HighchartsBaseChart {
|
|
|
166
174
|
// All responsive rules should be defined here to avoid overriding existing rules
|
|
167
175
|
setResponsiveOptions = () => {
|
|
168
176
|
let mobileChartOptions = this.commonChartOptions.getMobileOptions(this.xAxisTickIntervalMobile, this.yAxisTickIntervalMobile);
|
|
169
|
-
if (this.chartType === 'column') {
|
|
177
|
+
if (this.chartType === 'column' || this.chartType === 'boxplot') {
|
|
170
178
|
const mobileColumnChartOptions = this.columnChart.getColumnChartMobileOptions(
|
|
171
179
|
this.config,
|
|
172
180
|
this.useStackedLayout,
|
|
173
181
|
this.extraLines,
|
|
174
182
|
);
|
|
175
|
-
mobileChartOptions =
|
|
183
|
+
mobileChartOptions = mergeConfigs(mobileChartOptions, mobileColumnChartOptions);
|
|
176
184
|
}
|
|
177
185
|
|
|
178
186
|
if (!this.config.responsive) {
|
|
179
187
|
this.config.responsive = {};
|
|
180
188
|
}
|
|
181
189
|
|
|
190
|
+
const { desktopAllPlotLinesAndBands, mobileAllPlotLinesAndBands } = preparePlotLinesAndBands(
|
|
191
|
+
this.annotations,
|
|
192
|
+
this.rangeAnnotations,
|
|
193
|
+
this.rangeAnnotationsOptions,
|
|
194
|
+
this.referenceLineAnnotationsOptions,
|
|
195
|
+
this.commonChartOptions,
|
|
196
|
+
this.chartType,
|
|
197
|
+
);
|
|
198
|
+
|
|
182
199
|
let rules = [
|
|
183
200
|
{
|
|
184
201
|
condition: {
|
|
@@ -198,6 +215,7 @@ class HighchartsBaseChart {
|
|
|
198
215
|
},
|
|
199
216
|
chartOptions: {
|
|
200
217
|
annotations: this.annotationsOptions ? this.annotationsOptions.getAnnotationsOptionsMobile() : undefined,
|
|
218
|
+
...(mobileAllPlotLinesAndBands != {} ? mobileAllPlotLinesAndBands : null),
|
|
201
219
|
},
|
|
202
220
|
},
|
|
203
221
|
{
|
|
@@ -206,6 +224,7 @@ class HighchartsBaseChart {
|
|
|
206
224
|
},
|
|
207
225
|
chartOptions: {
|
|
208
226
|
annotations: this.annotationsOptions ? this.annotationsOptions.getAnnotationsOptionsDesktop() : undefined,
|
|
227
|
+
...(desktopAllPlotLinesAndBands != {} ? desktopAllPlotLinesAndBands : null),
|
|
209
228
|
},
|
|
210
229
|
},
|
|
211
230
|
];
|
|
@@ -238,6 +257,15 @@ class HighchartsBaseChart {
|
|
|
238
257
|
if (this.chartType === 'scatter') {
|
|
239
258
|
this.scatterChart.updateMarkers(currentChart);
|
|
240
259
|
}
|
|
260
|
+
if (this.chartType === 'columnrange') {
|
|
261
|
+
this.columnRangeChart.updateColumnRangeChartHeight(this.config, currentChart);
|
|
262
|
+
this.commonChartOptions.hideDataLabels(currentChart.series);
|
|
263
|
+
|
|
264
|
+
if (this.extraScatter > 0) {
|
|
265
|
+
const scatterSeries = currentChart.series.filter((series) => series.type === 'scatter');
|
|
266
|
+
this.scatterChart.updateMarkersForConfidenceLevels(scatterSeries);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
241
269
|
if (this.chartType != 'bar') {
|
|
242
270
|
this.commonChartOptions.adjustChartHeight(currentChart, this.percentageHeightDesktop, this.percentageHeightMobile);
|
|
243
271
|
}
|
|
@@ -257,6 +285,18 @@ class HighchartsBaseChart {
|
|
|
257
285
|
};
|
|
258
286
|
};
|
|
259
287
|
|
|
288
|
+
setRenderEvent = () => {
|
|
289
|
+
if (!this.config.chart.events) {
|
|
290
|
+
this.config.chart.events = {};
|
|
291
|
+
}
|
|
292
|
+
this.config.chart.events.render = (event) => {
|
|
293
|
+
const currentChart = event.target;
|
|
294
|
+
if (this.rangeAnnotationsOptions) {
|
|
295
|
+
this.rangeAnnotationsOptions.addLine(currentChart);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
};
|
|
299
|
+
|
|
260
300
|
// Set resize events - throttled to 50ms
|
|
261
301
|
// All resize events should be defined here to avoid overriding existing events
|
|
262
302
|
setWindowResizeEvent = () => {
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import ChartConstants from './chart-constants';
|
|
2
|
+
|
|
3
|
+
class ColumnRangeChart {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.constants = ChartConstants.constants();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
getColumnRangeChartOptions = () => {
|
|
9
|
+
return {
|
|
10
|
+
plotOptions: {
|
|
11
|
+
columnrange: {
|
|
12
|
+
color: this.constants.uncertaintyRangeColor, // Set the default color for the column range
|
|
13
|
+
pointWidth: 20, // Fixed bar height
|
|
14
|
+
pointPadding: 0,
|
|
15
|
+
groupPadding: 0,
|
|
16
|
+
borderWidth: 0,
|
|
17
|
+
borderRadius: 0,
|
|
18
|
+
dataLabels: {
|
|
19
|
+
enabled: false,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
xAxis: {
|
|
24
|
+
// Update the category label colours for bar charts
|
|
25
|
+
labels: {
|
|
26
|
+
style: {
|
|
27
|
+
color: this.constants.categoryLabelColor,
|
|
28
|
+
},
|
|
29
|
+
useHTML: false,
|
|
30
|
+
},
|
|
31
|
+
// remove the tick marks for bar charts
|
|
32
|
+
tickWidth: 0,
|
|
33
|
+
tickLength: 0,
|
|
34
|
+
gridlineWidth: 0,
|
|
35
|
+
tickColor: 'transparent',
|
|
36
|
+
title: { align: 'high', textAlign: 'middle', reserveSpace: false, rotation: 0, y: -25, useHTML: true },
|
|
37
|
+
},
|
|
38
|
+
yAxis: {
|
|
39
|
+
labels: {
|
|
40
|
+
rotation: 0,
|
|
41
|
+
useHTML: true,
|
|
42
|
+
style: {
|
|
43
|
+
whiteSpace: 'nowrap',
|
|
44
|
+
color: this.constants.categoryLabelColor,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
tickLength: 0,
|
|
48
|
+
tickWidth: 0,
|
|
49
|
+
tickColor: 'transparent',
|
|
50
|
+
gridlineWidth: 0,
|
|
51
|
+
title: {
|
|
52
|
+
// Override the y Axis title settings for bar charts where the y axis is horizontal
|
|
53
|
+
textAlign: 'right',
|
|
54
|
+
offset: undefined,
|
|
55
|
+
y: 0,
|
|
56
|
+
reserveSpace: true,
|
|
57
|
+
useHTML: false,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
legend: {
|
|
61
|
+
symbolRadius: 0,
|
|
62
|
+
itemStyle: {
|
|
63
|
+
fontSize: this.constants.defaultFontSize,
|
|
64
|
+
color: this.constants.legendLabelColor,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// This updates the height of the vertical axis and overall chart to fit the number of categories
|
|
71
|
+
// Note that the vertical axis on a bar chart is the x axis
|
|
72
|
+
updateColumnRangeChartHeight = (config, currentChart) => {
|
|
73
|
+
const numberOfCategories = config.xAxis.categories.length;
|
|
74
|
+
let barHeight = 20; // Height of each individual bar - set in bar-chart-plot-options
|
|
75
|
+
let groupSpacing = 0; // Space we want between category groups, or between series groups for cluster charts
|
|
76
|
+
let categoriesTotalHeight = 0;
|
|
77
|
+
let totalSpaceHeight = 0;
|
|
78
|
+
|
|
79
|
+
groupSpacing = 14;
|
|
80
|
+
categoriesTotalHeight = numberOfCategories * barHeight;
|
|
81
|
+
|
|
82
|
+
totalSpaceHeight = numberOfCategories * groupSpacing;
|
|
83
|
+
|
|
84
|
+
config.xAxis.height = categoriesTotalHeight + totalSpaceHeight;
|
|
85
|
+
const totalHeight = currentChart.plotTop + config.xAxis.height + currentChart.marginBottom;
|
|
86
|
+
if (totalHeight !== currentChart.chartHeight) {
|
|
87
|
+
currentChart.setSize(null, totalHeight, false);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
currentChart.redraw();
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default ColumnRangeChart;
|
|
@@ -81,15 +81,6 @@ class CommonChartOptions {
|
|
|
81
81
|
},
|
|
82
82
|
lineColor: this.constants.gridLineColor,
|
|
83
83
|
gridLineColor: this.constants.gridLineColor,
|
|
84
|
-
// Add zero line
|
|
85
|
-
plotLines: [
|
|
86
|
-
{
|
|
87
|
-
color: this.constants.zeroLineColor,
|
|
88
|
-
width: 1.5,
|
|
89
|
-
value: 0,
|
|
90
|
-
zIndex: 2,
|
|
91
|
-
},
|
|
92
|
-
],
|
|
93
84
|
// Add tick marks
|
|
94
85
|
tickWidth: 1,
|
|
95
86
|
tickLength: 6,
|
|
@@ -143,6 +134,25 @@ class CommonChartOptions {
|
|
|
143
134
|
|
|
144
135
|
getOptions = () => this.options;
|
|
145
136
|
|
|
137
|
+
// TODO: A future ticket will add support for other plot lines which are not
|
|
138
|
+
// reference line annotations, and will be styled like the zero line
|
|
139
|
+
// See ticket https://jira.ons.gov.uk/browse/CCB-63
|
|
140
|
+
getPlotLines = () => {
|
|
141
|
+
// Add zero line
|
|
142
|
+
return {
|
|
143
|
+
yAxis: {
|
|
144
|
+
plotLines: [
|
|
145
|
+
{
|
|
146
|
+
color: this.constants.zeroLineColor,
|
|
147
|
+
width: 1.5,
|
|
148
|
+
value: 0,
|
|
149
|
+
zIndex: 2,
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
|
|
146
156
|
getMobileOptions = (xAxisTickInterval, yAxisTickInterval) => {
|
|
147
157
|
return {
|
|
148
158
|
xAxis: {
|
|
@@ -165,7 +175,7 @@ class CommonChartOptions {
|
|
|
165
175
|
};
|
|
166
176
|
|
|
167
177
|
disableLegendForSingleSeries = (config) => {
|
|
168
|
-
if (config.series.length === 1) {
|
|
178
|
+
if (config.chart.type != 'boxplot' && config.series.length === 1) {
|
|
169
179
|
config.legend = {
|
|
170
180
|
enabled: false,
|
|
171
181
|
};
|
|
@@ -187,12 +197,15 @@ class CommonChartOptions {
|
|
|
187
197
|
x: 30, // Adjust label position to account for longer line
|
|
188
198
|
});
|
|
189
199
|
} else {
|
|
200
|
+
if (!symbol) return;
|
|
190
201
|
// Set the symbol size for bar / column series
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
202
|
+
else {
|
|
203
|
+
symbol.attr({
|
|
204
|
+
width: 12,
|
|
205
|
+
height: 12,
|
|
206
|
+
y: 8,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
196
209
|
}
|
|
197
210
|
});
|
|
198
211
|
}
|
package/components/chart/example-bar-chart-with-point-range-and-reference-line-annotations.njk
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{% from "components/chart/_macro.njk" import onsChart %}
|
|
2
|
+
|
|
3
|
+
{{
|
|
4
|
+
onsChart({
|
|
5
|
+
"chartType": "bar",
|
|
6
|
+
"description": "Volume sales, seasonally adjusted, Great Britain, January 2022 to January 2025",
|
|
7
|
+
"theme": "primary",
|
|
8
|
+
"title": "Food stores showed a strong rise on the month, while non-food stores fell",
|
|
9
|
+
"subtitle": "Figure 6: Upward contribution from housing and household services (including energy) saw the annual CPIH inflation rate rise",
|
|
10
|
+
"id": "uuid",
|
|
11
|
+
"caption": "Source: Monthly Business Survey, Retail Sales Inquiry from the Office for National Statistics",
|
|
12
|
+
"download": {
|
|
13
|
+
'title': 'Download Figure 1 data',
|
|
14
|
+
'itemsList': [
|
|
15
|
+
{
|
|
16
|
+
"text": "Excel spreadsheet (XLSX format, 18KB)",
|
|
17
|
+
"url": "#"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"text": "Simple text file (CSV format, 25KB)",
|
|
21
|
+
"url": "#"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"text": "Image (PNG format, 25KB)",
|
|
25
|
+
"url": "#"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"xAxis": {
|
|
30
|
+
"categories": [
|
|
31
|
+
"All retailing",
|
|
32
|
+
"All retailing excluding Automotive fuel",
|
|
33
|
+
"Food stores",
|
|
34
|
+
"Department stores",
|
|
35
|
+
"Other non-food stores",
|
|
36
|
+
"Textile clothing \u0026 footwear stores",
|
|
37
|
+
"Household goods stores",
|
|
38
|
+
"Non-store retailing",
|
|
39
|
+
"Automotive fuel"
|
|
40
|
+
],
|
|
41
|
+
"type": "linear"
|
|
42
|
+
},
|
|
43
|
+
"yAxis": {
|
|
44
|
+
"title": "Percent (%)"
|
|
45
|
+
},
|
|
46
|
+
"series": [
|
|
47
|
+
{
|
|
48
|
+
"data": [1.7, 2.1, 5.6, 0, -0.6, -2.7, -1.7, 2.4, -1.2],
|
|
49
|
+
"dataLabels": false,
|
|
50
|
+
"name": "Jan-25"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"annotations": [
|
|
54
|
+
{
|
|
55
|
+
"text": "A test point annotation",
|
|
56
|
+
"point": {"x": 2, "y": 3},
|
|
57
|
+
"labelOffsetX": 40,
|
|
58
|
+
"labelOffsetY": -30
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
"rangeAnnotations": [
|
|
62
|
+
{
|
|
63
|
+
"text": "A test x axis range annotation",
|
|
64
|
+
"range": {"axisValue1": 1, "axisValue2": 2},
|
|
65
|
+
"axis": "x",
|
|
66
|
+
"labelOffsetX": 10,
|
|
67
|
+
"labelOffsetY": -60
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"text": "A test y axis range annotation with a width of 80px",
|
|
71
|
+
"range": {"axisValue1": 5, "axisValue2": 6},
|
|
72
|
+
"axis": "y",
|
|
73
|
+
"labelOffsetX": -80,
|
|
74
|
+
"labelOffsetY": 220,
|
|
75
|
+
"labelWidth": 80
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
"referenceLineAnnotations": [
|
|
79
|
+
{
|
|
80
|
+
"text": "A test x axis reference line annotation",
|
|
81
|
+
"value": 8,
|
|
82
|
+
"axis": "x",
|
|
83
|
+
"labelOffsetY": -30
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"text": "A test y axis reference line annotation",
|
|
87
|
+
"value": 1.5,
|
|
88
|
+
"axis": "y",
|
|
89
|
+
"labelWidth": 100,
|
|
90
|
+
"labelOffsetX": 10,
|
|
91
|
+
"labelOffsetY": 140
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
})
|
|
95
|
+
}}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{% from "components/chart/_macro.njk" import onsChart %}
|
|
2
|
+
|
|
3
|
+
{{
|
|
4
|
+
onsChart({
|
|
5
|
+
"chartType": "columnrange",
|
|
6
|
+
"isChartInverted": true,
|
|
7
|
+
"description": "Volume sales, seasonally adjusted, Great Britain, January 2022 to January 2025",
|
|
8
|
+
"theme": "primary",
|
|
9
|
+
"title": "Food stores showed a strong rise on the month, while non-food stores fell",
|
|
10
|
+
"subtitle": "Figure 6: Upward contribution from housing and household services (including energy) saw the annual CPIH inflation rate rise",
|
|
11
|
+
"id": "uuid",
|
|
12
|
+
"caption": "Source: Monthly Business Survey, Retail Sales Inquiry from the Office for National Statistics",
|
|
13
|
+
"download": {
|
|
14
|
+
'title': 'Download Figure 1 data',
|
|
15
|
+
'itemsList': [
|
|
16
|
+
{
|
|
17
|
+
"text": "Excel spreadsheet (XLSX format, 18KB)",
|
|
18
|
+
"url": "#"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"text": "Simple text file (CSV format, 25KB)",
|
|
22
|
+
"url": "#"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"text": "Image (PNG format, 25KB)",
|
|
26
|
+
"url": "#"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"legend": true,
|
|
31
|
+
"xAxis": {
|
|
32
|
+
"categories": [
|
|
33
|
+
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
34
|
+
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
|
|
35
|
+
],
|
|
36
|
+
"type": "linear",
|
|
37
|
+
"title": "Categories"
|
|
38
|
+
},
|
|
39
|
+
"yAxis": {
|
|
40
|
+
"title": "Temperature ( °C )"
|
|
41
|
+
},
|
|
42
|
+
"series": [
|
|
43
|
+
{
|
|
44
|
+
"data": [
|
|
45
|
+
[-9.5, 8.0],
|
|
46
|
+
[-7.8, 8.3],
|
|
47
|
+
[-13.1, 9.2],
|
|
48
|
+
[-4.4, 15.7],
|
|
49
|
+
[-1.0, 20.8],
|
|
50
|
+
[3.1, 28.4],
|
|
51
|
+
[5.9, 27.0],
|
|
52
|
+
[4.6, 23.0],
|
|
53
|
+
[4.9, 19.3],
|
|
54
|
+
[-5.2, 11.6],
|
|
55
|
+
[],
|
|
56
|
+
[-10.5, 12.0],
|
|
57
|
+
[-12.1, 18.5]
|
|
58
|
+
],
|
|
59
|
+
"dataLabels": true,
|
|
60
|
+
"name": "Values"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"data": [1,2,3,4,5,6,7,8,9,10,3,11,12],
|
|
64
|
+
"marker": true,
|
|
65
|
+
"dataLabels": false,
|
|
66
|
+
"name": "Another test data source",
|
|
67
|
+
"type": "scatter"
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
})
|
|
71
|
+
}}
|