D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
davo
Full window
Github gist
Transition Between Three Views
Built with
blockbuilder.org
<!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>
https://d3js.org/d3.v3.min.js