Built with blockbuilder.org
forked from DarienLiang's block: Transition Between Three Views
license: mit |
Built with blockbuilder.org
forked from DarienLiang's block: Transition Between Three Views
Fruit | Count | |
---|---|---|
Apple | 12 | |
Pear | 4 | |
Orange | 13 | |
Cherry | 13 | |
Blueberry | 8 | |
Banana | 2 | |
Peach | 13 | |
Lemon | 5 | |
Watermelon | 15 | |
Lime | 24 | |
Mango | 16 | |
Grape | 10 | |
Kiwi | 8 | |
Pineapple | 15 | |
Date | 20 |
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
.axis { | |
font: 12px sans-serif; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.x.axis path { | |
display: none; | |
} | |
</style> | |
<body> | |
<script src="https://d3js.org/d3.v3.min.js"></script> | |
<script> | |
var m = [50, 50, 50, 50], | |
w = 960 - m[1] - m[3], | |
h = 450 - m[0] - m[2]; | |
var x, | |
y, | |
duration = 2000, | |
delay = 500; | |
var x2, | |
y2; | |
//var color = d3.scale.category10(); | |
// set color | |
var color = d3.scale.category20(); | |
var svg = d3.select("body").append("svg") | |
.attr("width", w + m[1] + m[3]) | |
.attr("height", h + m[0] + m[2]) | |
.append("g") | |
.attr("transform", "translate(" + m[3] + "," + m[0] + ")"); | |
var pie = d3.layout.pie() | |
.value(function(d) { | |
return d.count; | |
}); | |
var arc = d3.svg.arc(); | |
d3.csv("fruit.csv", function(error, data) { | |
data.forEach(function(d) { | |
d.fruit = d.Fruit; | |
d.count = +d.Count; | |
}); | |
x = d3.scale.ordinal() | |
.domain(data.map(function(d) { return d.fruit; })) | |
.rangeRoundBands([0, w], .2); | |
y = d3.scale.linear() | |
.domain([d3.max(data.map(function(d) { return d.count; })), 0]) | |
.range([0, h]); | |
x2 = d3.scale.ordinal() | |
.domain(data.map(function(d) { return d.fruit; })) | |
.range([0, w]); | |
// add pie but do not diaplay it | |
var g = svg.selectAll(".symbol") | |
.data(function() { return pie(data); }) | |
.enter() | |
.append("g") | |
.attr("class", "symbol"); | |
g.append("rect") | |
.style("fill", function(d) { | |
return color(d.data.fruit); | |
}) | |
.attr("x", function(d){ | |
return x(d.data.fruit); | |
}) | |
.attr("y", function(d){ | |
return y(d.data.count); | |
}) | |
.attr("width", x.rangeBand()) | |
.attr("height", function(d) { | |
return h - y(d.data.count); | |
}) | |
.attr("rx", 0) | |
.attr("ry", 0); | |
//draw bar chart first | |
g.append("path") | |
.style("fill", function(d) { | |
return color(d.data.fruit); | |
}); | |
g.append("text") | |
.attr("transform", function(d){ | |
return "translate(" + (x(d.data.fruit)+x.rangeBand()/3) + "," + (h+20) + ")"; | |
}) | |
.text(function(d) { | |
return d.data.fruit; | |
}); | |
//then use path element of bars do transition; | |
// without button | |
toPie(); | |
}); | |
function toPie(){ | |
var g = svg.selectAll(".symbol"); | |
g.selectAll("rect").remove(); | |
g.selectAll("path") | |
.transition() | |
.duration(duration) | |
.tween("arc", arcTween); | |
//The idea here is to first draw an arc like a bar, | |
//then tween the bar-like arc to the donut arc. | |
//Thus, the fruit is find the initial bar size and position: | |
//The initial bar height is approximated by the length of | |
//outside arc: barHeight = init_OuterRadius * init_Angle. | |
//So we can get the startAngle shown in f; | |
//(Note that: the measure of angle in d3 starts from vertical y: | |
// y angle | |
// | / | |
// | / | |
// | / | |
// |o/ | |
// |/ | |
// ) | |
function arcTween(d) { | |
var path = d3.select(this), | |
text = d3.select(this.parentNode).select("text"), | |
x0 = x(d.data.fruit), | |
y0 = h - y(d.data.count); //initial height | |
return function(t) { | |
var r = h / 2 / Math.min(1, t + 1e-3), | |
//a is stepping factor, starting from 1 to 0, | |
//as the timer t goes. | |
//A simper alternative: a = 1 - t; | |
a = Math.cos(t * Math.PI / 2), | |
xx = (-r + (a) * (x0 + x2.rangeBand()) + (1-a)*(w + h)/2), | |
yy = ((a) * h + (1 - a) * h/2), | |
f = { | |
innerRadius: (r - x.rangeBand() / (2 - a)) * a, | |
outerRadius: r, | |
//endAngle:0, | |
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)); | |
text.attr("transform", "translate(" + arc.centroid(f) + ")translate(" + xx + "," + yy + ")rotate(" + ((f.startAngle + f.endAngle) / 2 + 3 * Math.PI / 2) * 180 / Math.PI + ")"); | |
}; | |
} | |
} | |
function toBar(){ | |
var g = svg.selectAll(".symbol"); | |
//g.selectAll("rect").remove(); | |
g.selectAll("path") | |
.transition() | |
.duration(duration) | |
.tween("arc", arcTween); | |
//The idea here is to first draw an arc like a bar, | |
//then tween the bar-like arc to the donut arc. | |
//Thus, the fruit is find the initial bar size and position: | |
//The initial bar height is approximated by the length of | |
//outside arc: barHeight = init_OuterRadius * init_Angle. | |
//So we can get the startAngle shown in f; | |
//(Note that: the measure of angle in d3 starts from vertical y: | |
// y angle | |
// | / | |
// | / | |
// | / | |
// |o/ | |
// |/ | |
// ) | |
function arcTween(d) { | |
var path = d3.select(this), | |
text = d3.select(this.parentNode).select("text"), | |
x0 = x2(d.data.fruit), | |
y0 = h - y2(d.data.count); //initial height | |
var x2 = d3.scale.ordinal() | |
.domain(fruit.map(function(d) { return d.fruit; })) | |
.range([0, w]); | |
var y2 = y; | |
return function(t) { | |
t = 1-t; | |
var r = h / 2 / Math.min(1, t + 1e-3), | |
//a is stepping factor, starting from 1 to 0, | |
//as the timer t goes. | |
//A simper alternative: a = 1 - t; | |
a = Math.cos(t * Math.PI / 2), | |
xx = (-r + (a) * (x0 + x.rangeBand()) + (1 - a) * (w + h) / 2), | |
yy = ((a) * h + (1 - a) * h / 2), | |
f = { | |
innerRadius: (r - x.rangeBand() / (2 - a)) * 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)); | |
text.attr("transform", "translate(" + arc.centroid(f) + ")translate(" + xx + "," + yy + ")rotate(" + ((f.startAngle + f.endAngle) / 2 + 3 * Math.PI / 2) * 180 / Math.PI + ")"); | |
}; | |
} | |
} | |
</script> | |
</body> |