Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drag, drop and shape rotation with Raphael JS

I'm using RaphaelJS 2.0 to create several shapes in a div. Each shape needs to be able to be dragged and dropped within the bounds of the div, independently. Upon double clicking a shape, that shape needs to rotate 90 degrees. It may then be dragged and dropped and rotated again.

I've loaded some code onto fiddler: http://jsfiddle.net/QRZMS/. It's basically this:

    window.onload = function () {

        var angle = 0;

        var R = Raphael("paper", "100%", "100%"),
            shape1 = R.rect(100, 100, 100, 50).attr({ fill: "red", stroke: "none" }),
            shape2 = R.rect(200, 200, 100, 50).attr({ fill: "green", stroke: "none" }),
            shape3 = R.rect(300, 300, 100, 50).attr({ fill: "blue", stroke: "none" }),
            shape4 = R.rect(400, 400, 100, 50).attr({ fill: "black", stroke: "none" });
        var start = function () {
            this.ox = this.attr("x");
            this.oy = this.attr("y");
        },
        move = function (dx, dy) {
            this.attr({ x: this.ox + dx, y: this.oy + dy });
        },
        up = function () {

        };
        R.set(shape1, shape2, shape3, shape4).drag(move, start, up).dblclick(function(){
            angle -= 90;
            shape1.stop().animate({ transform: "r" + angle }, 1000, "<>");
        });


    }

The drag and drop is working and also one of the shapes rotates on double click. However, there are two issues/questions:

  1. How can I attach the rotation onto each shape automatically without having to hard-code each item reference into the rotate method? I.e. I just want to draw the shapes once, then have them all automatically exposed to the same behaviour, so they can each be dragged/dropped/rotated independently without having to explicitly apply that behaviour to each shape.

  2. After a shape has been rotated, it no longer drags correctly - as if the drag mouse movement relates to the original orientation of the shape rather than updating when the shape is rotated. How can I get this to work correctly so that shapes can just be dragged and rotated many times, seamlessley?

Many thanks for any pointers!

like image 446
Dan Avatar asked Nov 29 '22 03:11

Dan


2 Answers

I've tried several times to wrap my head around the new transform engine, to no avail. So, I've gone back to first principles.

I've finally managed to correctly drag and drop an object thats undergone several transformations, after trying to work out the impact of the different transformations - t,T,...t,...T,r,R etc...

So, here's the crux of the solution

var ox = 0;
var oy = 0;

function drag_start(e) 
{
};


function drag_move(dx, dy, posx, posy) 
{


   r1.attr({fill: "#fa0"});

   //
   // Here's the interesting part, apply an absolute transform 
   // with the dx,dy coordinates minus the previous value for dx and dy
   //
   r1.attr({
    transform: "...T" + (dx - ox) + "," + (dy - oy)
   });

   //
   // store the previous versions of dx,dy for use in the next move call.
   //
   ox = dx;
   oy = dy;
}


function drag_up(e) 
{
   // nothing here
}

That's it. Stupidly simple, and I'm sure it's occurred to loads of people already, but maybe someone might find it useful.

Here's a fiddle for you to play around with.

... and this is a working solution for the initial question.

like image 177
amadan Avatar answered Dec 10 '22 15:12

amadan


I solved the drag/rotate issue by re-applying all transformations when a value changes. I created a plugin for it.

https://github.com/ElbertF/Raphael.FreeTransform

Demo here:

http://alias.io/raphael/free_transform/

like image 40
Elbert Alias Avatar answered Dec 10 '22 15:12

Elbert Alias