-3

I am working on a draggable functionality. In that I have created an area (See attached Screenshot) in which I have to drag the images. But there is also one undraggable area in which I have to disable the draggable functionality.

Screenshot: https://prnt.sc/nl43fu

+-------+
|       |
|   D   |
|       |
|   +---+
|   |   |
|   | U |
|   |   |
+---+---+

D = Draggable, U = Undraggable

It would be great if someone can help on this issue. Your help might be grateful.

Twisty
  • 30,304
  • 2
  • 26
  • 45
Chirag Patel
  • 15
  • 1
  • 3

1 Answers1

0

Draggable containment uses the Box Model to identify boundaries for draggable items.

containment Type: Selector or Element or String or Array, Default: false

Constrains dragging to within the bounds of the specified element or region. Multiple types supported:

  • Selector: The draggable element will be contained to the bounding box of the first element found by the selector. If no element is found, no containment will be set.
  • Element: The draggable element will be contained to the bounding box of this element.
  • String: Possible values: "parent", "document", "window".
  • Array: An array defining a bounding box in the form [ x1, y1, x2, y2 ].

Ref: http://api.jqueryui.com/draggable/

So this means you need to create either complex boxes or build collision detection into your drag callback. When drag is triggered, it is passed an event and ui object. ui.position can be manipulated:

Current CSS position of the helper as { top, left } object. The values may be changed to modify where the element will be positioned. This is useful for custom containment, snapping, etc.

This can be difficult, so if this is a beggining project or something small, consider using Collision plugin: jQuery Dragging With Collision Detection

Consider the following primitive example.

$(function() {
  function log(obj) {
    var str = "T: " + obj.top + " L:, " + obj.left + ", R: " + obj.right + ", B: " + obj.bottom;
    $("#log").html(str);
  }

  function getObjectPos(obj) {
    var oPos = obj.position();
    oPos.right = oPos.left + obj.width();
    oPos.bottom = oPos.top + obj.height();
    return oPos;
  }

  function collision(a, b) {
    var col = false;
    var side;
    var r1 = getObjectPos(a);
    var r2 = getObjectPos(b);
    /*
    https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection
    rect1.x < rect2.x + rect2.width && rect1.x + rect1.width > rect2.x && rect1.y < rect2.y + rect2.height && rect1.y + rect1.height > rect2.y
   */
    if (r1.left < r2.right && r1.right > r2.left && r1.top < r2.bottom && r1.bottom > r2.top) {
      col = true;
    }
    return {
      col: col,
      right: r1.right > r2.left,
      left: r1.left > r2.right,
      bottom: r1.bottom > r2.bottom,
      top: r1.top > r2.top
    };
  }
  $("#draggable").draggable({
    containment: "#containment-wrapper",
    start: function(e, ui) {
      ui.helper.data("prev-pos", getObjectPos(ui.helper));
    },
    drag: function(e, ui) {
      var oPrevPos = ui.helper.data("prev-pos");
      var oPos = getObjectPos(ui.helper);
      console.log(oPrevPos, oPos);
      log(oPos);
      $("#containment-wrapper .no-drag").each(function(ind, el) {
        var c = collision(ui.helper, $(el));
        var col = c.col;
        var side;
        if (col) {
          switch (true) {
            case c.top:
              side = "top";
              break;
            case c.left:
              side = "left";
              break;
            case c.bottom:
              side = "bottom";
              break;
            case c.right:
              side = "right";
              break;
          }
          console.log("Collision: " + col, side, c);
          switch (side) {
            case "left":
            case "right":
              ui.position.left = oPrevPos.left
              break;
            case "top":
            case "bottom":
              ui.position.top = oPrevPos.top
              break;
          }
        } else {
          console.log("Collision: " + c.col, c);
          ui.helper.data("prev-pos", oPos);
        }
      });
    }
  });
});
.draggable {
  width: 100px;
  height: 100px;
  float: left;
  margin: 0;
  padding: 0;
  background: #CCC;
}

#containment-wrapper {
  width: 400px;
  height: 250px;
  border: 2px solid #ccc;
  padding: 10px;
  position: relative;
}

#containment-wrapper .no-drag {
  width: 100px;
  height: 100px;
  border: 2px solid #ccc;
  top: 168px;
  left: 318px;
  position: absolute;
}

.output {
  margin-top: -2em;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="containment-wrapper">
  <div id="draggable" class="draggable">
  </div>
  <div class="no-drag">
  </div>
</div>
<div id="log" class="output"></div>

This is a very basic example using some 2D Collision Detection. It's not great and could use improvement, yet you can see where to start.

Hope this helps.

Community
  • 1
  • 1
Twisty
  • 30,304
  • 2
  • 26
  • 45