Steve Brown
Steve Brown

Reputation: 1416

How can I animate a vector path being drawn with Raphael JS?

How can I animate a vector path being drawn with Raphael JS?

I have a set of coordinates that I would like to connect using Raphael JS.

On a grid, the coordinates are (x,y sets). I would like to start from one end and "connect the dots" as the user watches. The end product would look something like this:

Picture 9.png http://img213.imageshack.us/img213/8013/picture9my.png

Ideally, I would like to be able to make the paths curved so they would look more like this (coordinates added for reference):

Picture 10.png http://img534.imageshack.us/img534/1789/picture10fc.png

The coordinates are:

26,-6
14,-12
5,-20
11,-28
14,-37
5,-40

I've been searching Google and I have read through this question How to draw a vector path progressively? (Raphael.js) but I am trying to use Raphael.js specifically and the example on that page for Raphael.js does not seem to work nor does it talk about using multiple coordinate points for inputs.

Upvotes: 6

Views: 7319

Answers (2)

Kevin Nielsen
Kevin Nielsen

Reputation: 4433

Progressive Paths

Drawing a path progressively is easy to do. I dislike the second-most-accepted answer on this question because it recreates a path at every step, clearing the paper in between. Here's the utility function I've used time and time again:

function drawpath( canvas, pathstr, duration, attr, callback )
{
    var guide_path = canvas.path( pathstr ).attr( { stroke: "none", fill: "none" } );
    var path = canvas.path( guide_path.getSubpath( 0, 1 ) ).attr( attr );
    var total_length = guide_path.getTotalLength( guide_path );
    var last_point = guide_path.getPointAtLength( 0 );
    var start_time = new Date().getTime();
    var interval_length = 50;
    var result = path;        

    var interval_id = setInterval( function()
    {
        var elapsed_time = new Date().getTime() - start_time;
        var this_length = elapsed_time / duration * total_length;
        var subpathstr = guide_path.getSubpath( 0, this_length );            
        attr.path = subpathstr;

        path.animate( attr, interval_length );
        if ( elapsed_time >= duration )
        {
            clearInterval( interval_id );
            if ( callback != undefined ) callback();
                guide_path.remove();
        }                                       
    }, interval_length );  
    return result;
}

You can see it in action on my site.

This alone would make animating the progressive path construction of your points in a linear fashion absolutely simple. You'd simply compile your path...

var sequence_path = ["M26,-6", "L14,-12", "L5,-20", "L11,-28", "L14,-37", "L5,-40"];

And then pass it to whatever path animation function you've set up. In my case,

drawpath( paper, 
          sequence_path, 
          3500, 
          { stroke: 'black', 'stroke-width': 2, 'stroke-opacity': 1, fill: 'none', 'fill-opacity': 0 }, 
          function()
          {
              alert("All done");    // trigger whatever you want here
          } );

Curve Interpolation

Raphael 2.0's Catmull Rom feature makes curving gracefully between your points extremely straightforward (thanks to Erik Dahlström for pointing this out). All you need to do is construct a path using the 'R' command to move between points, and Raphael will do the rest.

function generateInterpolatedPath( points )
{
    var path_sequence = [];
    path_sequence.push( "M", points[0].x, points[0].y );
    path_sequence.push( "R" );
    for ( var i = 1; i < points.length; i++ )
    {
        path_sequence.push( points[i].x, points[i].y );
    }
    return path_sequence;
}

You can see all the pieces working together here.

Upvotes: 19

Erik Dahlstr&#246;m
Erik Dahlstr&#246;m

Reputation: 60966

You could also use Catmull Rom (see http://raphaeljs.com/reference.html#Paper.path) to get the smooth curve through the given points.

Live demo here (click to assign points, then shift-click to transition to Catmull Rom curve).

Upvotes: 3

Related Questions