Skip to content

Instantly share code, notes, and snippets.

@emepyc
Created December 11, 2012 01:17
Show Gist options
  • Save emepyc/4254927 to your computer and use it in GitHub Desktop.
Save emepyc/4254927 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.45582194222455524,"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 and g2 are the svg element that will be used to include the reusable pie charts
var g = d3.select("svg")
.append("g")
var g2 = d3.select("svg")
.append("g")
// data1 and data2 are used to test the transitions.
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 a few methods are defined (API):
// -x: The x position of the pie-chart
// -y: The y position of 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().x(138).y(320);
// First, pChart is called with the svg element to display the pie chart
pChart(g);
// Added a second pie chart
var pChart2 = pieChart().x(478).y(320);
pChart2(g2);
// 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);
var t2 = pChart2.transition().duration(500);
// The pie charts are updated twice with new data and the transition t
setTimeout(function(){pChart.max_counts(150).update(data1, t)}, 2000);
setTimeout(function(){pChart.max_counts(30).update(data2, t)}, 4000);
setTimeout(function(){pChart2.max_counts(40).update(data2, t2, 30)}, 2000);
setTimeout(function(){pChart2.max_counts(200).update(data1, t2, 30)}, 4000);
// pChart is the function returning the reusable pie-chart with transitions.
function pieChart() {
// Initial values:
// TODO: height should be substituted by max_height
var height=800;
var data = {counts : [1,1,1,1,1],
colors : ["green", "yellow", "red", "blue", "cyan"],
total : 5
}
var pie = d3.layout.pie()
.sort(null);
var max_counts = d3.sum(data.counts);
// 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 = pie_size_scale(data.total);
var posx = 420;
var posy = 258;
var paths = [];
var radiusFactor = 4;
var innerRadius = outerRadius / radiusFactor;
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
// chart is the returned closure
var chart = function(g) {
// 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) {
// The size of the pie chart (outerRadius) is dynamic.
var total_counts_extent = [0, chart.max_counts()];
console.log("max_counts: " + chart.max_counts());
var pie_size_scale = d3.scale.linear()
.range([height/10, height/5])
.domain(total_counts_extent);
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.data = function(value) {
if (!arguments.length) return data;
data = value;
return chart;
};
chart.max_counts = function(value) {
if (!arguments.length) return max_counts;
max_counts = value;
return chart;
};
chart.x = function(value) {
console.log(posx)
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