Skip to content

Instantly share code, notes, and snippets.

/_.md

Created December 11, 2012 01:14
Show Gist options
  • Save anonymous/4254902 to your computer and use it in GitHub Desktop.
Save anonymous/4254902 to your computer and use it in GitHub Desktop.
Reusable pie chart with transition
{"description":"Reusable pie chart with transition","endpoint":"","display":"svg","public":true,"require":[],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"tab":"edit","display_percent":0.5902953586497888,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"period","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"hidepanel":false}
// This snippet implements a reusable pie-chart with transitions.
// Its purpose is to experiment with reusable charts (and transitions)
// as explained in:
// http://bost.ocks.org/mike/chart/
// g is the svg element that will be used to include the reusable pie chart
var g = d3.select("svg")
.append("g")
// .attr("transform", "translate(" + 420 + "," + 258 + ")");
// max_counts only serves to affect the size of the pie-chart (its outerRadius)
var max_counts = 20;
// data1 and data2 are used to provide transition data.
var data1 = {counts : [2,6,7,2,1],
colors : ["green", "yellow", "red", "blue", "cyan"],
total : 18
};
var data2 = {counts : [1,1,1,10,2],
colors : ["green", "yellow", "red", "blue", "cyan"],
total : 15
};
// pChart is the reusable pie chart implementation.
// In this example only 4 methods are defined (API):
// -outerRadius: To provide the initial outer radius to the pie chart
// -data: to update the data used by the pie chart (here this is internally used by the update method)
// -update: to update the pie chart with new data + transition
// -transition: returns a transition closure that is used to pudate the pie-chart (via its update method)
var pChart = pieChart();
// First, pChart is called with the svg element to display the pie chart
pChart(g);
// t is a closure that knows how to perform transitions.
// It also has a method defined:
// duration: The duration of the transition.
var t = pChart.transition().duration(500);
// The pie chart is updated twice with new data and the transition t
setTimeout(function(){pChart.update(data1, t)}, 2000);
setTimeout(function(){pChart.update(data2, t)}, 4000);
// pChart is the function returning the reusable pie-chart with transitions.
function pieChart() {
// Initial values:
var width = 1228;
var height = 982;
var data = {counts : [1,1,1,1,1],
colors : ["green", "yellow", "red", "blue", "cyan"],
total : 5
}
var pie = d3.layout.pie()
.sort(null);
// The size of the pie chart (outerRadius) is dynamic.
var total_counts_extent = [0, max_counts];
var pie_size_scale = d3.scale.linear()
.range([height/10, height/5])
.domain(total_counts_extent)
var outerRadius;
// chart is the returned closure
var chart = function(g) {
var posx = 420;
var posy = 258;
var paths = []
var outerRadius = pie_size_scale(data.total);
var radiusFactor = 4;
var innerRadius = outerRadius / radiusFactor;
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
// path defined the parts of the pie chart.
// It is stored internally in the closure (i.e. not returned).
// In each path node we store its current value. This is needed for the transitions later
g.attr("transform", "translate(" + chart.x() + "," + chart.y() + ")");
var path = g.selectAll("path").data(pie(data.counts))
.enter().append("path")
.attr("fill", "white")
.attr("d", arc)
.each(function(d) { this._current = d; }); // store the initial values
// The pie-chart is feeded with the initial data and colouring
path.data(pie(data.counts))
.attr("fill", function(d,i) {return data.colors[i]});
// transition is a method on the pie chart that returns a transition closure
// This closure knows how to make the transition given new data for the pie chart.
chart.transition = function() {
var newT = function(path) {
var duration = 1500;
var delay = 0;
path.transition().delay(delay).duration(newT.duration()).attrTween("d", function(a) {
var i = d3.interpolate(this._current, a),
k = d3.interpolate(arc.outerRadius()(),pie_size_scale(data.total));
this._current = i(0);
return function(t) {
return arc.innerRadius(k(t)/radiusFactor).outerRadius(k(t))(i(t));
};
}); // redraw the arcs
}
// duration is a method that allows to change the duration of the transition
newT.duration = function(value) {
if (!arguments.length) return duration;
duration = value;
return newT
};
return newT;
}
// update is a method to update the pie-chart (given new data and a transition closure)
chart.update = function(data, trans) {
// We update the data variable and...
chart.data(data);
// ...the pie paths with the new data.
paths.data(pie(data.counts))
// call the transition closure
trans(paths);
paths = path;
return;
}
paths = path;
return;
} // end of chart closure
// Some methods are defined over the chart: outerRadius and data
chart.outerRadius = function(value) {
if (!arguments.length) return outerRadius;
outerRadius = value;
return chart;
}
chart.data = function(value) {
if (!arguments.length) return data;
data = value;
return chart;
}
chart.x = function(value) {
if (!arguments.length) return posx;
posx = value;
return chart;
}
chart.y = function(value) {
if (!arguments.length) return posy;
posy = value;
return chart;
}
return chart;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment