Raphael.fn.svg_frames = function() {
  var paper = this;

  var frames = {
    list: [],
    interval: 333,
    paper: paper,

    add: function() {
      for (var i=0; i<arguments.length; i++) {
        this.list.push(this.draw_object(arguments[i]));
      }
    },

    draw_object: function(attr_list) {
      var objects = [];
      for (var i=0; i<attr_list.length; i++) {
        objects.push(this.draw_part(attr_list[i]));
      };
      return objects;
    },

    draw_part: function(attrs) {
      return paper
        .path(attrs.d)
        .attr(this.attrs_from_string(attrs.style))
        .hide();
    },

    attrs_from_string: function(str) {
      var attrs = {};
      str.split(/;/).
        forEach(function(pair) {
          var kv = pair.split(/:/);
          attrs[kv[0]] = kv[1];
        });
      return attrs;
    },

    show_frame: function(frame) {
      for (var i=0; i<frame.length; i++) {
        frame[i].show();
      };
    },

    hide_frame: function(frame) {
      for (var i=0; i<frame.length; i++) {
        frame[i].hide();
      };
    },


    translate: function(x, y, seconds) {
      for (var i=0; i<this.list.length; i++) {
        this.translate_object(this.list[i], x, y, seconds);
      }
      this.toggle_frames(seconds);
    },

    toggle_frames: function(seconds, count) {
      var self = this;
      if (!count) count=1;

      var frames = this.list;
      var current_frame = count % frames.length;

      for (var i=0; i<frames.length; i++) {
        if (i == current_frame) {
          this.show_frame(frames[i]);
        }
        else {
          this.hide_frame(frames[i]);
        }
      }


      if (count < Math.floor(seconds / self.interval)) {
        var fn = function(){self.toggle_frames(seconds, count+1);};
        setTimeout(fn, self.interval);
      }
    },

    translate_object: function(frame, x, y, seconds) {
      // offset between end coordinates and current location
      var x_diff = x - frame[0].getBBox().x;
      var y_diff = y - frame[0].getBBox().y;

      for (var i=0; i<frame.length; i++) {
        var obj = frame[i];
        // calculate path starting from absolute coordinates and moving
        // relatively from there by the offset
        var p = "M " + obj.getBBox().x + " " + obj.getBBox().y +
               " l " + x_diff          + " " + y_diff;

         // animate along that path
         obj.animateAlong(p, seconds);
      };
    },

    getBBox: function() {
      return this.list[0][this.list[0].length-1].getBBox();
    },

    attr: function() {
      // delegate to last object in first frame
      var obj = this.list[0][this.list[0].length-1];
      return obj.attr.apply(obj, arguments);
    },

    onAnimation: function(fn) {
      this.list[0][0].onAnimation(fn);
    }

  };

  // TODO: accept an array argurment
  frames.add.apply(frames, arguments);
  frames.show_frame(frames.list[0]);

  return frames;
};

@@ -130,32 +130,42 @@
   add: function(
+frame_list
 ) %7B%0A      for (v
@@ -174,25 +174,26 @@
  i=0; i%3C
-arguments
+frame_list
 .length;
@@ -240,25 +240,26 @@
 _object(
-arguments
+frame_list
 %5Bi%5D));%0A 
@@ -1114,30 +1114,25 @@
 ction(x, y, 
-second
+m
 s) %7B%0A      f
@@ -1221,22 +1221,17 @@
 , x, y, 
-second
+m
 s);%0A    
@@ -1244,35 +1244,68 @@
     
-this.toggle_frames(seconds)
+if (ms && ms %3E 50) this.toggle_frames(ms);%0A      return this
 ;%0A  
@@ -1338,22 +1338,17 @@
 unction(
-second
+m
 s, count
@@ -1680,17 +1680,16 @@
      %7D%0A%0A
-%0A
       if
@@ -1709,22 +1709,17 @@
 h.floor(
-second
+m
 s / self
@@ -1779,22 +1779,17 @@
 _frames(
-second
+m
 s, count
@@ -1894,22 +1894,17 @@
 , x, y, 
-second
+m
 s) %7B%0A   
@@ -1982,33 +1982,46 @@
 iff = x - frame%5B
-0
+frame.length-1
 %5D.getBBox().x;%0A 
@@ -2048,17 +2048,30 @@
 - frame%5B
-0
+frame.length-1
 %5D.getBBo
@@ -2437,36 +2437,113 @@
     
- obj.animateAlong(p, seconds
+if (ms && ms %3E 50)%0A          obj.animateAlong(p, ms);%0A        else%0A          obj.translate(x_diff, y_diff
 );%0A 
@@ -2919,43 +2919,70 @@
 %0A%0A  
-// TODO: accept an array 
+if (arguments.length %3E 1)%0A    frames.add(
 argu
-r
 ment
+s);%0A  else
 %0A
+  
   fr
@@ -2993,23 +2993,9 @@
 .add
-.apply(frames, 
+(
 argu
@@ -2999,19 +2999,23 @@
 rguments
+%5B0%5D
 );%0A
+%0A
   frames

Make translate work like raphael's core translate. The plugin can now take a list of frame arguments or a single array