Last active
August 29, 2015 14:10
-
-
Save kevinwarne/dbfd40c60fe5efe5db72 to your computer and use it in GitHub Desktop.
Toggle Between Bar Chart and Pie Chart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
{"x":2009,"y":1259}, | |
{"x":2010,"y":1319}, | |
{"x":2011,"y":1279}, | |
{"x":2012,"y":1450} | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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