Skip to content

Instantly share code, notes, and snippets.

@kevinwarne
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevinwarne/dbfd40c60fe5efe5db72 to your computer and use it in GitHub Desktop.
Save kevinwarne/dbfd40c60fe5efe5db72 to your computer and use it in GitHub Desktop.
Toggle Between Bar Chart and Pie Chart
[
{"x":2009,"y":1259},
{"x":2010,"y":1319},
{"x":2011,"y":1279},
{"x":2012,"y":1450}
]
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
svg {
font-family: "Helvetica Neue", Helvetica;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis path {
stroke-opacity: 0.3;
}
rect, path{
stroke:black;
stroke-width:0.5;
}
.bar-drilldown-bar{
pointer-events:none;
opacity:0.9;
}
text{
font-size:12px;
}
body{
cursor:pointer;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 30, bottom: 30, left: 60},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var chart_svg = d3
.select('body')
.append('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var data;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .2);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var xAxisGroup = chart_svg
.append('g')
.attr('class','x axis')
.attr("transform", "translate(0," + height + ")");
var yAxisGroup = chart_svg
.append('g')
.attr('class','y axis')
.attr("transform", "translate(0,0)");
var barGroup = chart_svg
.append('g')
.attr('class','bars');
var arcGroup = chart_svg
.append('g')
.attr('class','arcs');
var color = d3.scale.category20();
d3.json('data.json', function(error,json){
if (error) return console.warn(error);
data = json;
toBarChart(true)
})
var arc = d3.svg.arc();
var duration = 1000;
var state = 'Bar';
d3.select('body').on('click', toggleChart)
function toggleChart(){
if(state == 'Bar')
toPieChart()
else
toBarChart(false)
}
function toPieChart(){
//clear click event and reset after duration
d3.select('body').on('click', function(){return})
setTimeout(function(){d3.select('body').on('click', toggleChart)},duration)
state = 'Pie';
//fade out x and y axis contents
xAxisGroup.selectAll('*').transition().duration(duration/2).style('opacity',0).remove();
yAxisGroup.selectAll('*').transition().duration(duration/2).style('opacity',0).remove();
var pie = d3.layout.pie()
.value(function(d) { return d.x; });
var arcs = arcGroup.selectAll('path.arc').data(pie(data))
var enteredArcs = arcs.enter()
.append("path")
.attr('class','arc')
.style("fill", function(d) { return color(d.data.x); })
.transition()
.duration(duration)
.tween('arc',function(d){return arcTween(d,d3.select(this),false)})
//remove bars at beginning of transition (slight overlap to avoid flickering)
barGroup.selectAll('*').transition().duration(10).style('opacity',0).remove()
}
//tween function from mbostock's show reel example, text functionality omitted
function arcTween(d, path, reverse_flag) {
var x0 = x(d.data.x),
y0 = height - y(d.data.y);
return function(t) {
if(reverse_flag)
t = 1-t;
var r = height / 2 / Math.min(1, t + 1e-3),
a = Math.cos(t * Math.PI / 2),
xx = (-r + (a) * (x0 + x.rangeBand()) + (1 - a) * (width + height) / 2),
yy = ((a) * height + (1 - a) * height / 2),
f = {
innerRadius: r - x.rangeBand() / (2 - a),
outerRadius: r,
startAngle: a * (Math.PI / 2 - y0 / r) + (1 - a) * d.startAngle,
endAngle: a * (Math.PI / 2) + (1 - a) * d.endAngle
};
path.attr("transform", "translate(" + xx + "," + yy + ")");
path.attr("d", arc(f));
};
}
function toBarChart(init){
//clear click event and reset after duration
d3.select('body').on('click', function(){return})
setTimeout(function(){d3.select('body').on('click', toggleChart)},duration)
state = 'Bar';
x.domain(data.map(function(d){return d.x}))
y.domain([0, d3.max(data, function(d) { return d.y; })]);
//fade in x and y axis
xAxisGroup.transition().duration(duration/2).styleTween('opacity',function(){d3.interpolate(0,1)}).call(xAxis);
yAxisGroup.transition().duration(duration/2).styleTween('opacity',function(){d3.interpolate(0,1)}).call(yAxis);
var bars = barGroup.selectAll('g.bar').data(data);
var enteredBars = bars.enter()
.append('g')
.attr('class','bar')
.attr("transform", function(d, i) { return "translate(" + (x(d.x)) + ",0)"; });
enteredBars.append('rect');
var barRects = bars.select('rect')
.attr("y", function(d) { return y(d.y); })
.attr("height", function(d) { return height - y(d.y); })
.attr("width", x.rangeBand())
.style("fill", function(d) { return color(d.x); })
.style('opacity',0)
//if init, fade in rectangles otherwise delay until duration end and then show rectangles
if(init)
barRects.transition().duration(duration/2).style('opacity',1)
else
setTimeout(function(){barRects.style('opacity',1)},duration-10)
//tween the arcs to bar positions
arcGroup.selectAll('path.arc')
.transition()
.duration(duration)
.tween('arc',function(d){return arcTween(d,d3.select(this),true)})
.remove();
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment