Stackoverflow

How to make elements follow an animated path (using a shadow guide).

by andersand

JavaScript

/**
 *
 * Click on the blue circle to launch the animation
 *
 * @tag Stackoverflow
 */
var r = Raphael(0, 0, "100%", "100%");

(function() {
    var paths = ["M0 100 L200 100", "M0 100 S100 400 200 100"];
    var line = r.path(paths[0]).attr({fill: "none"}),
        elattrs = [{path: paths[0]},{path: paths[1]}],
        now = 1;
    var guide = r.path(paths[1]).attr({stroke: "#ddd"});
    var len = guide.getTotalLength();
    var f = len/4; // 4 = num circles + 1
    var c1 = r.circle(50, 100, 5).attr({fill: 'red'}),
        c2 = r.circle(100, 100, 5).attr({fill: 'red'}),
        c3 = r.circle(150, 100, 5).attr({fill: 'red'});

    r.circle(40, 40, 20).attr({fill: 'blue'}).click(function() {
        now = now ? 0 : 1;
        line.stop().animate(elattrs[now], 1000, 'elastic');
        if (now) {
            var p1 = guide.getPointAtLength(f),
                p2 = guide.getPointAtLength(f*2),
                p3 = guide.getPointAtLength(f*3);
            c1.stop().animate({cx: p1.x, cy: p1.y}, 1000, 'elastic');
            c2.stop().animate({cx: p2.x, cy: p2.y}, 1000, 'elastic');
            c3.stop().animate({cx: p3.x, cy: p3.y}, 1000, 'elastic');
        }
        else {
            c1.stop().animate({cx: 50,  cy: 100}, 1000, 'elastic');
            c2.stop().animate({cx: 100, cy: 100}, 1000, 'elastic');
            c3.stop().animate({cx: 150, cy: 100}, 1000, 'elastic');
        }
    });
})();