Skip to content

Instantly share code, notes, and snippets.

@mbostock
Last active December 26, 2017 23:25
Show Gist options
  • Save mbostock/1346395 to your computer and use it in GitHub Desktop.
Save mbostock/1346395 to your computer and use it in GitHub Desktop.
Pie Chart Update, I
license: gpl-3.0

This variation of a donut chart demonstrates how to update values. Clicking on the radio buttons changes the displayed metric.

Next: Animation

apples oranges
53245 200
28479 200
19697 200
24037 200
40245 200
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: auto;
position: relative;
width: 960px;
}
text {
font: 10px sans-serif;
}
form {
position: absolute;
right: 10px;
top: 10px;
}
</style>
<form>
<label><input type="radio" name="dataset" value="apples" checked> Apples</label>
<label><input type="radio" name="dataset" value="oranges"> Oranges</label>
</form>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var color = d3.scale.category20();
var pie = d3.layout.pie()
.value(function(d) { return d.apples; })
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 100)
.outerRadius(radius - 20);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
d3.tsv("data.tsv", type, function(error, data) {
var path = svg.datum(data).selectAll("path")
.data(pie)
.enter().append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc);
d3.selectAll("input")
.on("change", change);
var timeout = setTimeout(function() {
d3.select("input[value=\"oranges\"]").property("checked", true).each(change);
}, 2000);
function change() {
var value = this.value;
clearTimeout(timeout);
pie.value(function(d) { return d[value]; }); // change the value function
path = path.data(pie); // compute the new angles
path.attr("d", arc); // redraw the arcs
}
});
function type(d) {
d.apples = +d.apples;
d.oranges = +d.oranges;
return d;
}
</script>
@micha149
Copy link

Hey, these are my first Steps on updating elements. I think understand the concepts of data(), enter() and exit(), but my code doesn't work as expected. My dom structure for each segement should look like this:

<g class="arc>
    <a xlink:href="#">
        <path d="..." fill="red" stroke="white" />
    </a>
</g> 

All works well on creating the initial structure, but not on updating the data. My path elements do still deal with the data from the previos data attachment and are not updated correctly. exit() seems to work fine. Here's what I'm doing:

// Apply data        
g = svg.selectAll(".arc")
    .data(this._pieData);

// Add new ones
g.enter().append("g")
    .attr("class", "arc")
    .on("mouseover", $.proxy(this._onSegmentMouseOver, null, this))
    .on("mouseout", $.proxy(this._onSegmentMouseOut, null, this))
    .append('a')
        .attr('xlink:href', function(d, index) { return '?score=' + index; })
        .append("path")
            .style("stroke", "white");    

// Update arcs and colors
g.selectAll("path")
    .attr("d", self._getArc)
    .style("fill", function(d, ka, index) { return self._getColor(index); });

// Remove overhead
g.exit().remove();

this._pieData is updated on each data change with a d3 pie layout function. After that this update method is called. Complete code can be found on my github repository: https://github.com/micha149/classroom/blob/feature/graphs/app/Resources/public/js/chart.breakdown.js#L109-L135

Any suggestions?

@imported1809
Copy link

Does anyone have any suggestions for adding a responsive legend to this chart? I want to add one, but every time I try a different snippet of legend code the text is not a function of the data, instead just has 0,1,2,3,4,5 next to the colour boxes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment