1

One often wants to make a set of objects in Raphael draggable, but using .transform() to do so can be maddening. Say you start like this:

var paper = Raphael(0, 0, 500, 500);
var set = paper.set();
set.push(paper.circle(100,100,35), paper.circle(150,150,15));    
set.attr("fill", "orange");
set.data("myset", set);

set.drag(
    function(dx, dy, x, y, e) {
        this.data('myset').transform("T" + dx + "," + dy);
    },
    function(x, y, e) {},
    function(e) {}
);

If you try this out, you see it works once. But if you drag, stop, then drag again, it resets the position to 0,0 relative to the original position, as you'd expect from .transform(). No good.

A variant of this question has been touched on here, and the respondent suggested prepending transforms with "...". That's all fine and good, but for two things:

  • you still have to track previous position, since you don't want to translate by (dx,dy) on every call of dragmove, which will send the objects flying off the screen.
  • I worry about creating a monster transform if an object is dragged many times. (Though maybe I shouldn't.)

My tentative solution is to track the offset from the original positioning in another key/value pair, like so:

var paper = Raphael(0, 0, 500, 500);

var set = paper.set();
set.push(
    paper.circle(100,100,35),
    paper.circle(150,150,15)
);    
set.attr("fill", "orange");
set.data("myset", set);
set.data("position", [0,0]);
var current_position = [0,0];

set.drag(
    function(dx, dy, x, y, e) {
        this.data('myset').transform("T" + (this.data("position")[0] + dx) + "," + (this.data("position")[1] + dy));
        current_position = [dx,dy];
    },
    function(x, y, e) {

    },
    function(e) {
        this.data('myset').data("position", [
            this.data("position")[0] += current_position[0],
            this.data("position")[1] += current_position[1]
        ]);
    }
);

You can see it in action here.

It works, but it feels incredibly sloppy. I must be missing something obvious, right?

Community
  • 1
  • 1
Chris Wilson
  • 6,599
  • 8
  • 35
  • 71
  • As the respondent to the variant question you mention above, I would like to point out that I didn't entirely approve of my own suggestion =) I have found this to be a recurrent problem and I'm sure that there must be a cleaner solution; I'm just not sure what it might be yet. – Kevin Nielsen Mar 13 '13 at 21:16

1 Answers1

0

My answer is similar to your last variant:

var onmove = function (dx,dy){
    this.transform(this.default_transform+'T'+dx+','+dy); 
},
  onstart = function (){
    this.default_transform = this.transform();
},
  onend = function(){
    this.default_transform = this.transform();
};

set.drag(onmove, onstart, onend);

Don't worry it won't create a long long line of transformations because Raphael converts everything to one whole matrix transformation so it doesn't build up each time you move an object.

Roman
  • 3,799
  • 4
  • 30
  • 41