Skip to content

Instantly share code, notes, and snippets.

@milroc
Created July 6, 2012 22:18
Show Gist options
  • Save milroc/3063069 to your computer and use it in GitHub Desktop.
Save milroc/3063069 to your computer and use it in GitHub Desktop.
Area encoding to help a friend

Code to help Walter Gunter Jr. (@wegunterjr) with learning d3.js. based on: http://jsfiddle.net/wegunterjr/r92zG/

This is a variation of a stacked bar chart, where an additional dimension is mapped to width of the section. This additional dimension causes unnecessary complexity for the user.

Normal bar charts use a 1-dimensional area encoding (or redundantly encodes position and area), namely that the bars are all comparable in size, but fixed to one dimension.

By adding a second dimension (regardless of whether it is aesthetically pleasing), the usefulness of the encoding is still mapped to the area. Namely that the reader will interpret the smaller area as meaningful. Therefore it is recommended to map these dimensions with data that have a directly proportional relationship.

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<link type="text/css" rel="stylesheet" href="style.css"/>
</head>
<body>
<div id="chart"></div>
<script src="http://mbostock.github.com/d3/d3.js?2.7.2"></script>
<script src="src.js"></script>
</body>
</html>
// Inspired by Lee Byron's test data generator.
function bumpLayer(n, o) {
function bump(a) {
var x = 1 / (.1 + Math.random()),
y = 2 * Math.random() - .5,
z = 10 / (.1 + Math.random());
for (var i = 0; i < n; i++) {
var w = (i / n - y) * z;
a[i] += x * Math.exp(-w * w);
}
}
var a = [], i;
for (i = 0; i < n; ++i) a[i] = o + o * Math.random();
for (i = 0; i < 5; ++i) bump(a);
return a.map(function(d, i) { return {x: i, y: d, w: Math.random()*100}; });
}
var n = 4, // number of layers
m = 5, // number of samples per layer
stack = d3.layout.stack(),
layers = stack(d3.range(n).map(function() { return bumpLayer(m, .1); })),
yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); }),
wGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.w; })});
var margin = {top: 40, right: 10, bottom: 20, left: 10},
width = 600 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(d3.range(m))
.rangeRoundBands([0, width], .08);
var y = d3.scale.linear()
.domain([0, yStackMax])
.range([height, 0]);
var color = d3.scale.category10()
.domain(d3.range(n - 1))
.range(["#EA8825", "#FCBC6E", "#FF5800", "#F58025"])
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(0)
.tickPadding(6)
.orient("bottom");
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) { return color(i); });
var rect = layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("x", function(d) { return x(d.x) + (x.rangeBand() * (1 - d.w / wGroupMax)) / 2; })
// .attr("x", function(d) { return x(d.x); })
.attr("y", height)
.attr("width", function(d) { return x.rangeBand() * d.w / wGroupMax; })
.attr("height", 0);
rect.transition()
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); });
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
body {
background-color: steelblue;
color: white;
}
svg text {
fill: white;
font-size: 16px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment