chris Frisina
chris Frisina

Reputation: 19688

transition a circle into a line by unrolling it with SVG and d3

For a project we are trying to make a circle into a line (and back again) while it is rotating along a linear path, much like a tire rotates and translates when rolling on a road, or a curled fore finger is extended and recurled into the palm.

In this Fiddle, I have a static SVG (the top circle) that rotates along the linear black path (which is above the circle, to mimic a finger extending) that is defined in the HTML.

I also use d3 to generate a "circle" that is made up of connected points (and can unfurl if you click on/in the circle thanks to @ChrisJamesC here ), and is translated and rotated in the function moveAlongLine when you click on the purple Line:

function moveAlongLine() {
  circle.data([lineData])
  .attr("transform", "translate(78.5,0) rotate(-90, 257.08 70) ")
  .duration(1000)
  circle.on("click", transitionToCircle)
}

The first problem is that the .duration(1000) is not recognized and throws a Uncaught TypeError: Object [object Array] has no method 'duration' in the console, so there is a difference between the static definition of dur in SVG and dynamically setting it in JS/D3, but this is minor.

The other is should the transform attributes be abstracted from one another like in the static circle? in the static circle, the translate is one animation, and the rotation is another, they just have the same star and duration, so they animate together. How would you apply both in d3?

The challenge that I can not get, is how to let it unroll upwards(and also re-roll back), with the static point being the top center of the circle also being the same as the leftmost point on the line.

these seem better:

this seems really complicated but potential:

this seems complicated and clunky:

A couple of notes:

Upvotes: 3

Views: 2245

Answers (2)

chris Frisina
chris Frisina

Reputation: 19688

I ended up using the same function that generates the circle as in the question, and did a bit of thinking, and it seemed like I wanted an animation that looked like a finger unrolling like this fiddle. This lead me to the math and idea needed to make it happen in this fiddle.

The answer is an array of arrays, with each nested array being a line in the different state, and then animate by interpolating between the points.

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

and the animation(s)

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

Upvotes: 1

Alvin K.
Alvin K.

Reputation: 4379

(Note: This should be in comments but not enough spacing)

  1. Circle Animation Try the radial wipe from SO. Need to tweak it so angle starts at 180 and ends back at same place (line#4-6,19) and move along the X-axis (line#11) on each interation. Change the <path... attribute to suit your taste.

  2. Line Animation Grow a line from single point to the length (perimeter) of the circle.

  3. Sync both animation so that it appears good on all browsers (major headache!).

Upvotes: 0

Related Questions