Skip to content

Instantly share code, notes, and snippets.

@wayneminton
Forked from mbostock/.block
Last active August 29, 2015 14:07
Show Gist options
  • Save wayneminton/a12b563819b04a3555aa to your computer and use it in GitHub Desktop.
Save wayneminton/a12b563819b04a3555aa to your computer and use it in GitHub Desktop.
Pie Chart with Legend

Pie Chart with Legend

Combination of mbostock's Pie Chart Example Gist and ZJONSSON's d3.legend Gist. Useful to me when data labels are too big to write over the pie chart itself. Probably obvious to veterans, but here it is anyway.

// d3.legend.js
// (C) 2012 [email protected]
// MIT licence
(function() {
d3.legend = function(g) {
g.each(function() {
var g= d3.select(this),
items = {},
svg = d3.select(g.property("nearestViewportElement")),
legendPadding = g.attr("data-style-padding") || 5,
lb = g.selectAll(".legend-box").data([true]),
li = g.selectAll(".legend-items").data([true])
lb.enter().append("rect").classed("legend-box",true)
li.enter().append("g").classed("legend-items",true)
svg.selectAll("[data-legend]").each(function() {
var self = d3.select(this)
items[self.attr("data-legend")] = {
pos : self.attr("data-legend-pos") || this.getBBox().y,
color : self.attr("data-legend-color") != undefined ? self.attr("data-legend-color") : self.style("fill") != 'none' ? self.style("fill") : self.style("stroke")
}
})
items = d3.entries(items).sort(function(a,b) { return a.value.pos-b.value.pos})
li.selectAll("text")
.data(items,function(d) { return d.key})
.call(function(d) { d.enter().append("text")})
.call(function(d) { d.exit().remove()})
.attr("y",function(d,i) { return i+"em"})
.attr("x","1em")
.text(function(d) { ;return d.key})
li.selectAll("circle")
.data(items,function(d) { return d.key})
.call(function(d) { d.enter().append("circle")})
.call(function(d) { d.exit().remove()})
.attr("cy",function(d,i) { return i-0.25+"em"})
.attr("cx",0)
.attr("r","0.4em")
.style("fill",function(d) { console.log(d.value.color);return d.value.color})
// Reposition and resize the box
var lbbox = li[0][0].getBBox()
lb.attr("x",(lbbox.x-legendPadding))
.attr("y",(lbbox.y-legendPadding))
.attr("height",(lbbox.height+2*legendPadding))
.attr("width",(lbbox.width+2*legendPadding))
})
return g
}
})()
age population
<5 2704659
5-13 4499890
14-17 2159981
18-24 3853788
25-44 14106543
45-64 8819342
≥65 612463
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.arc path {
stroke: #fff;
}
.legend rect {
fill:white;
stroke:black;}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="d3.legend.js"></script>
<script>
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.population; });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
d3.csv("data.csv", function(error, data) {
data.forEach(function(d) {
d.population = +d.population;
});
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.attr("data-legend", function(d) { return d.data.age; })
.attr("data-legend-pos", function(d, i) { return i; })
.style("fill", function(d) { return color(d.data.age); });
g.append("text")
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.style("text-anchor", "middle");
var padding = 20,
legx = radius + padding,
legend = svg.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + legx + ", 0)")
.style("font-size", "12px")
.call(d3.legend);
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment