Built with blockbuilder.org
xxxxxxxxxx
<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