HTMLcopy
1
<div id="container"></div>
CSScopy
6
1
html, body, #container {
2
width: 100%;
3
height: 100%;
4
margin: 0;
5
padding: 0;
6
}
JavaScriptcopy
x
1
anychart.onDocumentReady(function () {
2
var data = preprocessData([
3
['2016', 'Rel 04', 18],
4
['2016', 'Rel 06', 13],
5
['2016', 'Rel 10', 17],
6
['2017', 'Rel 02', 4],
7
['2017', 'Rel 04', 13],
8
['2017', 'Rel 06', 12],
9
['2017', 'Rel 08', 6],
10
['2017', 'Rel 10', 17],
11
['2018', 'Rel 02', 12],
12
['2018', 'Rel 06', 9],
13
['2018', 'Rel 10', 15]
14
]);
15
16
var chart = anychart.column();
17
18
// configure global settings for series labels
19
chart.labels({position:'top'});
20
21
// add subcategory names to the meta of one of the series
22
chart.column(data.mapAs({'year': 0, 'value': 2, 'sub-category': 1}));
23
24
// use subcategory names as names of X-axis ticks
25
chart.xScale().names('sub-category');
26
27
chart.xAxis().labels().rotation(90);
28
chart.xAxis().labels().anchor("center");
29
chart.xAxis().overlapMode('allow-overlap');
30
31
// set a container and draw the chart
32
chart.container('container').draw();
33
34
// calculate extra axes
35
createTwoLevelAxis(chart, data);
36
});
37
38
function preprocessData(data){
39
// to make beautiful spacing between categories, add
40
// several empty lines with the same category names to the data
41
if (data.length > 0) {
42
// add one to the beginning of the array
43
data.unshift([data[0][0]]);
44
// add one more to the end of the data
45
data.push([data[data.length - 1][0]]);
46
// add two empty items every time the category name changes,
47
// to each category
48
for (var i = 2; i < data.length - 1; i++) {
49
var previous = data[i-1][0];
50
var current = data[i][0];
51
if (current!=previous) {
52
data.splice(i, 0, [previous], [current]);
53
i = i+2;
54
}
55
else {
56
data.splice(i, 0, [previous]);
57
i += 1;
58
}
59
}
60
}
61
return anychart.data.set(data);
62
}
63
64
function createTwoLevelAxis(chart, data, padding){
65
// subcategory names
66
var names = [];
67
// ticks for axes based on on main categories
68
var ticks = [];
69
// weights of ticks (to make spacing between categories by using
70
// the empty lines created in preprocessData)
71
var weights = [];
72
// the iterator feature allows us to go over data, so
73
// create an iterator for the new breakdown
74
var iter = data.mapAs({'category': 0, 'sub-category': 1}).getIterator();
75
while(iter.advance()) {
76
var name = iter.get('category');
77
var value = iter.get('sub-category');
78
// store category names
79
names.push(name);
80
// when the border between categories is identified, create a tick
81
if (name && names[names.length - 1] != names[names.length - 2]) {
82
ticks.push(iter.getIndex());
83
}
84
// assign weight to the tick
85
weights.push(value?0.5:0.2);
86
}
87
88
// create a custom scale
89
var customScale = anychart.scales.ordinal();
90
// supply values from the chart to the scale
91
customScale.values(chart.xScale().values());
92
// names and ticks of main categories only
93
customScale.names(names);
94
customScale.ticks(ticks);
95
96
// synchronize weights with the chart scale
97
chart.xScale().weights(weights);
98
99
// disable ticks along the main axis
100
chart.xAxis(0).ticks(false);
101
102
// create an extra chart axis
103
chart.xAxis(1)
104
.scale(customScale)
105
.orientation('top')
106
.ticks(true);
107
108
chart.xAxis(1).ticks().length(60).position('center');
109
chart.xAxis(1).labels().offsetY(30);
110
111
chart.xGrid(0).scale(customScale);
112
113
chart.title('Year / Release');
114
115
//format tooltip title
116
chart.tooltip().titleFormat("{%year}");
117
118
//format tooltip body
119
chart.tooltip().format("{%sub-category}: {%value}");
120
}