[76] | 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> |
---|