3

I am Trying to tweak this example http://raphaeljs.com/graffle.html to restrict the drag to within the container svg.

Somewhat like http://bl.ocks.org/1557377 or http://jqueryui.com/demos/draggable/#constrain-movement Basically I want to restrict objects moving out from the bounding box while dragging.

Here is the tweaked code added to move function ( http://jsfiddle.net/f4mFQ/1/ )

    if(thisBox.x < 0){
        ddx = 0;
    }else if(thisBox.x>width-thisBox.width ){
        ddx = width-thisBox.width;
    }else {
        ddx = this.ox + dx;
    }

    if(thisBox.y < 0){
        ddy = 0;
    }else if(thisBox.y>height-thisBox.height ){
        ddy = height-thisBox.height;
    }else{
        ddy = this.oy + dy;
    }

This partially works, when rectangle is moved beyond boundary it kind of dances on the edge! while the circle and ellipse get stuck to the edge.

So how to restrict element drag with constrained movement within parent bounding box in this case svg

Prashant Bhate
  • 10,907
  • 7
  • 47
  • 82

2 Answers2

4

One issue is that you're when you set ddx or ddy to be positioned on a side you then feed that value back as the center point of the ellipses so they 'snap' off to the side.

The second thing is you do your computations on the top left of the bounding box of this, not the actual calculated position of this (ox + dx). That's what's causing the confusion.

This isn't the prettiest implementation but I wanted to minimize the changes to your code, replace the move function with this one:

 move = function (dx, dy) {
    var width =this.paper.width,
    height = this.paper.height,
    thisBox = this.getBBox()
    //, box = {
    //     "x"      :thisBox.width,
    //     "y"      :thisBox.height,
    //     "x2"     :width-thisBox.width,
    //     "y2"     :height-thisBox.height,
    //     "width"  :width-thisBox.width,
    //     "height" :height-thisBox.height
    // };
    // var outOfBound=!Raphael.isBBoxIntersect(thisBox,box)
    ;

    console.log(thisBox.width,width,thisBox.x,thisBox
                ,this.ox);

    var ddx = this.ox + dx;
    var ddy = this.oy + dy;
    if (this.type == 'ellipse') { 
        ddx -= thisBox.width / 2;
        ddy -= thisBox.height / 2;
    }

    if(ddx < 0){
        ddx = 0;
    }else if(ddx>width-thisBox.width ){
        ddx = width-thisBox.width;
    }

    if(ddy < 0){
        ddy = 0;
    }else if(ddy>height-thisBox.height ){
        ddy = height-thisBox.height;
    }

    var att = this.type == "rect" ? {x: ddx, y: ddy} : {cx: ddx + (thisBox.width / 2), cy: ddy + (thisBox.height / 2)};
    this.attr(att);


    for (var i = connections.length; i--;) {
        r.connection(connections[i]);
    }
    r.safari();
} 

At the start we calculate ddx and ddy as the top left based on the position of this. (Adjusted if it's a ellipse, as ox and oy are the center co-ordinates).

Then it's much the same as before, although when we set the value back we re-adjust the values for the ellipse. You could change what values are stored/used to avoid the duplicate calculation.

That works for me.

Edit

Copied code into it's own fiddle.

SpaceDog
  • 3,249
  • 1
  • 17
  • 25
  • I can't test in jsfiddle due to an issue with dragging and Raphael on this machine (I need to use a hacked version of the library). But this should work: http://jsfiddle.net/SpaceDog/cYDPX/ – SpaceDog Sep 03 '13 at 10:15
  • Tested on a different computer, this version does what you want: http://jsfiddle.net/cYDPX/1/ which is just the code I posted originally. I copied your code and replaced your `move` function which mine. – SpaceDog Sep 03 '13 at 11:26
  • @PrashantBhate did the fiddle I posted at the end of the edit of my answer work for you? – SpaceDog Sep 06 '13 at 00:02
2

Hi I have updated the fiddle with this code, this seems working although not perfect,

The code changed

       if (thisBox.x < 0) {
            ddx = 0 + thisBox.width/2;//the position 0 was problem
        } else if (thisBox.x > width - thisBox.width) {
            ddx = width - thisBox.width;
        } else {
            ddx = this.ox +dx;
        }

        if (thisBox.y < 0) {
            ddy = 0+thisBox.height/2;//the position 0 was problem
        } else if (thisBox.y > height - thisBox.height) {
            ddy = height - thisBox.height;
        } else {
            ddy = this.oy + dy;
        }

I have updated the fiddle

Also I have updated some CSS to make it more clear and error free.

Update: Vibration,

I have updated fiddle2 that removes vibration on the top and left side,

Please check and reply

Also see this fiddle3 that works with the rounds/ellipses well but have problem with rectangle's I think there is something I must have missed, but working fine with ellipses so that should help

MarmiK
  • 5,639
  • 6
  • 40
  • 49
  • thanks for the suggestions. However this codes doesn't fix the issue of vibrating element when it id dragged past the border. Just click on one of the element and drag it past the edge to see what I mean – Prashant Bhate Sep 03 '13 at 09:49
  • Yes it do vibrate/dance but this is not getting beyond line what previously getting stuck beyond line. Check it, I will see if there is some smoothing effect :) – MarmiK Sep 03 '13 at 10:15
  • @PrashantBhate Have you seen the updated fiddle last two without vibration effect – MarmiK Sep 05 '13 at 10:11