/**
* With this demo, you are able to get the idea of transition and intepolate with D3
*/
// the 3 sets of data we would like to visualize
var data = [10, 20, 50];
// surely, create a svg workspace first
var theSvgG = d3.select('body').append('svg').attr({
width: 500,
height: 500
}).append('g').attr('transform', 'translate(300, 150)');
// the color of the 3 annuluses we will assign later
var colorScale = d3.scale.ordinal()
.range(['#ff00a3', '#f0ff00', '#00f0f0'])
// our main utils/data handler class
var DataHandler = function (data) {
// let's follow CommonJS a little bit
var exports = this;
// sum the array elements as a single circle radian
var sumData = data.reduce(function (a, b) {
return a + b;
});
// percentage of each array element
var percentageOfCircle = [];
var percentageOfCircle = function (i) {
return percentageOfCircle[i] || (percentageOfCircle[i] = data[i] / sumData)
}
// store end angle for all array elements
var endAngleOf = []
var endAngleOfDataI = function (i, value) {
if (typeof (value) !== 'undefined') {
endAngleOf[i] = value;
} else {
return endAngleOf[i] || 0
}
}
// get radian of an array element
var getRadianByDataI = function (radian, index) {
return radian * percentageOfCircle(index)
}
exports = {
endAngleOfDataI: endAngleOfDataI,
getRadianByDataI: getRadianByDataI
}
return exports;
}
// instantiate
var dataHandler = new DataHandler(data);
// the arc Path d generator
var arc = d3.svg.arc()
.innerRadius(100)
.outerRadius(130)
// we will generate startAngle value based on last sector's endAngle
.startAngle(function (d, index, interpolate) {
return dataHandler.endAngleOfDataI(index - 1);
})
// its startAngle + its radian = its endAngle
.endAngle(function (d, index, interpolate) {
var theStartAngle = dataHandler.endAngleOfDataI(index - 1);
var theRadian = dataHandler.getRadianByDataI(interpolate, index);
var endAngle = theStartAngle + theRadian;
dataHandler.endAngleOfDataI(index, endAngle);
return endAngle;
});
// the donut group
var theDonutG = theSvgG.selectAll('.donut-sector')
.data(data)
// enter state
.enter()
.append('g')
.attr('class', '.donut-sector');
// append a Path into each group
theDonutG.append('path')
.attr({
'stroke': '#ff00ff',
'stroke-width': 5,
'fill': 'white'
})
.transition()
.duration(2000)
// dynamically change Path d with d3 interpolate
.attrTween('d', function (d, index) {
// get the interpolator to generate value from 0 to 2 PI radian
// in accordance to the t (from 0 to 1) passed in later
var i = d3.interpolate(0, 2 * Math.PI)
return function (t) {
var interpolateOutput = arc(d, index, i(t));
return interpolateOutput;
}
})
.attr('fill', function (d) {
// style it with animation as well
return colorScale(d)
});