Circle unroll to line revolving

by chrisfrisina

HTML

<script src="http://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css">

CSS

.b2l-circle {
    stroke:black;
    stroke-width:1;
    fill:none;
    opacity: 1;
}

JavaScript

var numberOfPoints = 45;
var totalPoints = numberOfPoints;
var radius = 12;
var margin = {top: 5, left: 17};
var marginleft = margin.left;
var margintop = margin.top;
var lineLength = 2 * radius * Math.PI;
var lineDivision = lineLength/totalPoints;
var cx = 17;
var cy = 17;
var dur = 3000/numberOfPoints;

var circleStates = [];
for (i=0; i<totalPoints; i++){
    //circle portion
    var circleState = $.map(Array(numberOfPoints), function (d, j) {
      var x = marginleft + radius + lineDivision*i + radius * Math.sin(2 * j * Math.PI / (numberOfPoints - 1));
      var y =  margintop + radius - radius * Math.cos(2 * j * Math.PI / (numberOfPoints - 1));
      return { x: x, y: y};
    })
    circleState.splice(numberOfPoints-i);
    //line portion
    var lineState = $.map(Array(numberOfPoints), function (d, j) {
      var x = marginleft + radius + lineDivision*j;
      var y =  margintop;
      return { x: x, y: y};
    })
    lineState.splice(i);
    //together
    var individualState = lineState.concat(circleState);
    circleStates.push(individualState);
}
var lineData = $.map(Array(numberOfPoints), function (d, i) {
    var y = margin.top;
    var x = margin.left + i * lineLength / (numberOfPoints - 1)
    return {x: x, y: y}
});
var pathFunction = d3.svg.line()
    .x(function (d) {return d.x;})
    .y(function (d) {return d.y;})
    .interpolate("basis"); // bundle | basis | linear | cardinal is also an option

//The SVG Container
var svgContainer = d3.select("body").append("svg");
//The Circle SVG Path we draw
var circle = svgContainer.append("g")
    .append("path")
    .data([circleStates[0]])
    .attr("d", pathFunction)
    .attr("class", "b2l-circle");

function unroll() {
    for(i=0; i<numberOfPoints; i++){
        circle.data([circleStates[i]])
            .transition()
            .delay(dur*i)
            .duration(dur)
            .ease("linear")
            .attr('d', pathFunction)            
    }
}

d3.timer(unroll);