Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EaselJS: glitchy drag/drop

I have a bitmap inside of a container. When I drag the container the cursor changes to the edit-text shape, and also the image jumps to the bottom-right side of the cursor (as though I'm holding the image from the top-left corner and dragging it).

Here's my code just so you can see that I've RTFM:

function createIcon(imgPath) {
    var image = new Image();
    image.onload = function () {
        var img = new createjs.Bitmap(event.target)

        var con = new createjs.Container();
        con.x = 160;
        con.y = 100;
        con.addChild(img);
        stage.addChild(con);

        con.on("pressmove", function(evt) {
            evt.currentTarget.x = evt.stageX;
            evt.currentTarget.y = evt.stageY;
            stage.update();
        });

        stage.update();
    }

    image.src = imgPath;
}

Any ideas what's wrong?

like image 578
Mossi Avatar asked Apr 03 '14 06:04

Mossi


2 Answers

To prevent the jumping you would have to add an additional step before the pressmove:

con.on('mousedown', function(evt) {
    var ct = evt.currentTarget,
        local = ct.globalToLocal(evt.stageX, evt.stageY),
        nx = ct.regX - local.x,
        ny = ct.regY - local.y;
    //set the new regX/Y
    ct.regX = local.x;
    ct.regY = local.y;
    //adjust the real-position, otherwise the new regX/Y would cause a jump
    ct.x -= nx;
    ct.y -= ny;
});

This will set the new regX/Y to the current's mouse-position to prevent the shape/image from jumping.

For the cursor: You could either set this via CSS:

canvas {
    cursor: default !important; /* in this case you couldn't set any other cursor via EaselJS though */
}

OR you can set this via EaselJS: http://www.createjs.com/Docs/EaselJS/classes/DisplayObject.html#property_cursor

con.cursor = "default"; //or 'pointer'...or whatever cursor you want it to be
// you have to activate enableMouseOver though on the stage for this to work
like image 119
olsn Avatar answered Nov 10 '22 07:11

olsn


Though the solution provided by @olsn most certainly works, using the regX/regY to offset the object to account for the current mouse position might lead to difficulties when subsequently transforming the object.

E.g. if you want to rotate the object around its center, you will want to have the regX/regY reset to object width/2 and object height/2. This will reintroduce the glitch, though at a later stage in your object manipulation.

Given scenarios like this, I like to prevent using regX/regY to prevent dragging glitches.

Alternatively, I take note of the mouse position on dragstart, and measure the mouse movement while dragging. By applying this movement to the objects x/y position, the object will appear to move with the mouse, simulating dragging.

As shown in this fiddle and in the following code:

function enableDrag(obj) {
  obj.on("mousedown", dragstart);
  obj.on("pressmove", drag);
};

function dragstart(evt) {
  dragging = false;
}

function drag(evt) {
    // register object starting point and mousedrag (stage) starting point
  if (!dragging || !dragging.startCoords || !dragging.stageCoords) {
    dragging = evt.currentTarget;
    dragging.startCoords = {x: dragging.x, y: dragging.y};
    dragging.stageCoords = {x: evt.stageX, y: evt.stageY};
  }

  // calculate mouse offset after move, relative to starting point, subtract this movement from object coords (move)
  dragging.stageMove = {x: dragging.stageCoords.x - evt.stageX, y: dragging.stageCoords.y - evt.stageY};
  dragging.objectMove = {x: dragging.startCoords.x - dragging.stageMove.x, y: dragging.startCoords.y - dragging.stageMove.y};

  // apply movement to object
  evt.currentTarget.x = dragging.objectMove.x;
  evt.currentTarget.y = dragging.objectMove.y;

  stage.update(); //update stage without passing through ticker for higher FPS
}
like image 4
Pim Schaaf Avatar answered Nov 10 '22 08:11

Pim Schaaf