D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
DarienLiang
Full window
Github gist
Transition
Built with
blockbuilder.org
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script> <style> </style> <script> console.log(d3); // test if d3 is loaded //background stuff var barWidth = 65, //barWidth = d3.scale.ordinal().rangeBand(), barPadding = 5; var //graphWidth = 15 * (barWidth + barPadding) - barPadding, m = { left: 50, top: 50, right: 50, bottom: 50 }, graphWidth = 960 - m.left - m.right, graphHeight = 450 - m.top - m.bottom, totalHeight = 450, totalWidth = 960; // set color var color = d3.scale.category20(); /***************** First Transition: Scatter2Bar ********************/ d3.csv('fruit.csv', function(err, rawData) { if(err) console.log(err); // start here! var fruit = rawData.map(function(d){ return { f_name : d.Fruit, f_count : +d.Count } }); // the largest number of fruits var countMax = d3.max(fruit, function(d){return d.f_count;}); // how many kinds of fruits var vari_num = 15; var x = d3.scale.ordinal() .domain(fruit.map(function(d) { return d.f_name; })) .range([0, graphWidth]); var y = d3.scale.linear() .domain([countMax, 0]) .range([0, graphHeight]); var radius = 50 var rscale = d3.scale.linear() .domain([0, vari_num]) .range([0, radius]); var svg = d3.select('body') .append('svg') .attr('width', totalWidth) .attr('height', totalHeight); var yAxis = d3.svg.axis().scale(y).orient("left"); //space between bar var axisPadding = 5; var yAxisNodes = svg.append('g') .attr('transform', 'translate(' + (m.left - axisPadding) + ',' + m.top + ')') .attr('class','yAxis') .call(yAxis); ystyleAxisNodes(yAxisNodes); var graphGroup = svg.append('g') .attr('transform', 'translate(' + m.left + ',' + m.top + ')'); //set bar charts function xloc(d, i) { return i * (barWidth + barPadding); } function yloc(d) { return y( d.f_count); } function translator(d, i) { return "translate(" + xloc(d, i) + "," + yloc(d) + ")"; } var eleGroup = graphGroup.selectAll('g') .data(fruit) .enter() .append('g') .attr('class','eleBar') .attr('transform', translator); eleGroup.append('rect') .attr({ fill: function (d) { return color(d.f_name); }, width: function(d){return rscale(d.f_count);}, height: function(d){return rscale(d.f_count);}, rx:function(d){return 0.5*rscale(d.f_count);}, ry:function(d){return 0.5*rscale(d.f_count);}, opacity:0.8 }) .transition() //.delay(2000) .duration(800) .attr({ width: barWidth, height: barWidth, rx:barWidth/2, ry:barWidth/2 }) .transition() //.delay(3000) .duration(1500) .attr({ width: barWidth, height: function (d) { return y(countMax - d.f_count); }, rx:0, ry:0 }); var textTranslator = "translate(" + barWidth / 2 + "," + barWidth / 4 + ")"; function texttranslator1(d) { return "translate(" + 0.5*rscale(d.f_count) + "," + - barWidth / 4 + ")"; } eleGroup.append('text') .text(function(d) { return d.f_name; }) .attr({ fill: 'black', 'alignment-baseline': 'before-edge', 'text-anchor': 'middle', transform: texttranslator1 }) .style('font', '10px Lucida Console') .transition() //.delay(2000) .duration(800) .attr("transform", textTranslator); /****************** Second Transition: Bar2Pie *********************/ //call the function after a period of time setTimeout(toPie, 5000); function toPie(){ // remove y-axis and original bars d3.select('.yAxis').remove(); d3.selectAll('.eleBar').remove(); // add a pie layout var pie = d3.layout.pie() .value(function(d) { return d.f_count; }); // initial arc (bar-like arc -> pie-like arc) var arc = d3.svg.arc(); function xLocPie(d, i) { return i * (barWidth + barPadding); } function yLocPie(d) { return y( d.data.f_count); } function translatorPie(d, i) { return "translate(" + xLocPie(d, i) + "," + yLocPie(d) + ")"; } // add pie var eleGroupPie = graphGroup.selectAll("g") .data(pie(fruit)) .enter() .append("g") .attr("class", "elePie") .attr("transform", translatorPie); // reconstruct a bar chart eleGroupPie.append("rect") .attr({ fill: function(d) { return color(d.data.f_name); }, width: barWidth, height: function(d) { return y(countMax - d.data.f_count); }, //x: function(d) { return x(d.data.f_name); }, //y: function(d) { return y(d.data.f_count); }, rx:0, ry:0, opacity: 0.8 }) .attr("class", "rectPie"); eleGroupPie.append("path") .style("fill", function(d) { return color(d.data.f_name); }); var textTranslatorPie = "translate(" + barWidth / 2 + "," + barWidth / 4 + ")"; eleGroupPie.append('text') .text(function(d) { return d.data.f_name; }) .attr({ fill: 'black', 'alignment-baseline': 'before-edge', 'text-anchor': 'middle', transform: textTranslatorPie }) .style('font', '10px Lucida Console'); var pieGroup = svg.selectAll(".elePie"); /* */ pieGroup.selectAll("path") .transition() .duration(4000) .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) { pieGroup.selectAll(".rectPie").remove(); var path = d3.select(this), text = d3.select(this.parentNode).select("text"), x2 = d3.scale.ordinal() .domain(fruit.map(function(d) { return d.f_name; })) .rangeRoundBands([0, graphWidth], .2), y2 = d3.scale.linear() .domain([countMax, 0]) .range([0, graphHeight]), x0 = x2(d.data.f_name), y0 = graphHeight - y2(d.data.f_count); //initial height return function(t) { var r = graphHeight / 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) * (graphWidth + graphHeight) / 2)-200, yy = ((a) * graphHeight + (1 - a) * graphHeight/2)-250, f = { innerRadius: (r - x2.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 + ")"); }; } } }); function ystyleAxisNodes(axisNodes) { axisNodes.selectAll('.domain') .attr({ fill: 'none', 'stroke-width': 1, stroke: 'black' }); axisNodes.selectAll('.tick line') .attr({ fill: 'none', 'stroke-width': 1, stroke: 'black' }); } </script> <body> <h1> Animated Transitions </h1> </body>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js