Create a gist now

Instantly share code, notes, and snippets.

@mbostock /.block
Last active Dec 26, 2017

What would you like to do?
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>

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?

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