/** * 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) });