Built with blockbuilder.org
Last active
October 27, 2019 20:07
-
-
Save DarienLiang/ab9195cdfb03aeb90dd6c6e70464d86b to your computer and use it in GitHub Desktop.
Transition Between Three Views
This file contains hidden or 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
license: mit |
This file contains hidden or 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
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 |
This file contains hidden or 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> | |
.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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment