1 | <!DOCTYPE html> |
---|
2 | <html> |
---|
3 | <head> |
---|
4 | <title>Marimekko Chart</title> |
---|
5 | <script type="text/javascript" src="../../d3.js"></script> |
---|
6 | <script type="text/javascript" src="../../d3.layout.js"></script> |
---|
7 | <style type="text/css"> |
---|
8 | |
---|
9 | body { |
---|
10 | font: 10px sans-serif; |
---|
11 | } |
---|
12 | |
---|
13 | rect { |
---|
14 | stroke: #000; |
---|
15 | } |
---|
16 | |
---|
17 | svg { |
---|
18 | shape-rendering: crispEdges; |
---|
19 | } |
---|
20 | |
---|
21 | </style> |
---|
22 | </head> |
---|
23 | <body> |
---|
24 | <script type="text/javascript"> |
---|
25 | |
---|
26 | var w = 960, |
---|
27 | h = 500, |
---|
28 | m = 20, |
---|
29 | x = d3.scale.linear().range([0, w - 3 * m]), |
---|
30 | y = d3.scale.linear().range([0, h - 2 * m]), |
---|
31 | z = d3.scale.category10(), |
---|
32 | n = d3.format(",d"), |
---|
33 | p = d3.format("%"); |
---|
34 | |
---|
35 | var svg = d3.select("body").append("svg:svg") |
---|
36 | .attr("width", w) |
---|
37 | .attr("height", h) |
---|
38 | .append("svg:g") |
---|
39 | .attr("transform", "translate(" + 2 * m + "," + m + ")"); |
---|
40 | |
---|
41 | d3.json("marimekko.json", function(data) { |
---|
42 | var offset = 0; |
---|
43 | |
---|
44 | // Nest values by segment. We assume each segment+market is unique. |
---|
45 | var segments = d3.nest() |
---|
46 | .key(function(d) { return d.segment; }) |
---|
47 | .entries(data); |
---|
48 | |
---|
49 | // Compute the total sum, the per-segment sum, and the per-market offset. |
---|
50 | // You can use reduce rather than reduceRight to reverse the ordering. |
---|
51 | // We also record a reference to the parent segment for each market. |
---|
52 | var sum = segments.reduce(function(v, p) { |
---|
53 | return (p.offset = v) + (p.sum = p.values.reduceRight(function(v, d) { |
---|
54 | d.parent = p; |
---|
55 | return (d.offset = v) + d.value; |
---|
56 | }, 0)); |
---|
57 | }, 0); |
---|
58 | |
---|
59 | // Add x-axis ticks. |
---|
60 | var xtick = svg.selectAll(".x") |
---|
61 | .data(x.ticks(10)) |
---|
62 | .enter().append("svg:g") |
---|
63 | .attr("class", "x") |
---|
64 | .attr("transform", function(d) { return "translate(" + x(d) + "," + y(1) + ")"; }); |
---|
65 | |
---|
66 | xtick.append("svg:line") |
---|
67 | .attr("y2", 6) |
---|
68 | .style("stroke", "#000"); |
---|
69 | |
---|
70 | xtick.append("svg:text") |
---|
71 | .attr("y", 8) |
---|
72 | .attr("text-anchor", "middle") |
---|
73 | .attr("dy", ".71em") |
---|
74 | .text(p); |
---|
75 | |
---|
76 | // Add y-axis ticks. |
---|
77 | var ytick = svg.selectAll(".y") |
---|
78 | .data(y.ticks(10)) |
---|
79 | .enter().append("svg:g") |
---|
80 | .attr("class", "y") |
---|
81 | .attr("transform", function(d) { return "translate(0," + y(1 - d) + ")"; }); |
---|
82 | |
---|
83 | ytick.append("svg:line") |
---|
84 | .attr("x1", -6) |
---|
85 | .style("stroke", "#000"); |
---|
86 | |
---|
87 | ytick.append("svg:text") |
---|
88 | .attr("x", -8) |
---|
89 | .attr("text-anchor", "end") |
---|
90 | .attr("dy", ".35em") |
---|
91 | .text(p); |
---|
92 | |
---|
93 | // Add a group for each segment. |
---|
94 | var segments = svg.selectAll(".segment") |
---|
95 | .data(segments) |
---|
96 | .enter().append("svg:g") |
---|
97 | .attr("class", "segment") |
---|
98 | .attr("xlink:title", function(d) { return d.key; }) |
---|
99 | .attr("transform", function(d) { return "translate(" + x(d.offset / sum) + ")"; }); |
---|
100 | |
---|
101 | // Add a rect for each market. |
---|
102 | var markets = segments.selectAll(".market") |
---|
103 | .data(function(d) { return d.values; }) |
---|
104 | .enter().append("svg:a") |
---|
105 | .attr("class", "market") |
---|
106 | .attr("xlink:title", function(d) { return d.market + " " + d.parent.key + ": " + n(d.value); }) |
---|
107 | .append("svg:rect") |
---|
108 | .attr("y", function(d) { return y(d.offset / d.parent.sum); }) |
---|
109 | .attr("height", function(d) { return y(d.value / d.parent.sum); }) |
---|
110 | .attr("width", function(d) { return x(d.parent.sum / sum); }) |
---|
111 | .style("fill", function(d) { return z(d.market); }); |
---|
112 | }); |
---|
113 | |
---|
114 | </script> |
---|
115 | </body> |
---|
116 | </html> |
---|