【问题标题】:Draggable UI - How to define undraggable area?Draggable UI - 如何定义不可拖动区域?
【发布时间】:2019-05-06 14:28:05
【问题描述】:

我正在开发一个可拖动的功能。在那我创建了一个区域(见附件截图),我必须在其中拖动图像。但是还有一个不可拖动的区域,我必须在其中禁用可拖动功能。

截图:https://prnt.sc/nl43fu

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

D = 可拖动,U = 不可拖动

如果有人可以帮助解决这个问题,那就太好了。您的帮助将不胜感激。

【问题讨论】:

    标签: jquery-ui


    【解决方案1】:

    可拖动容器使用盒子模型来识别可拖动项目的边界。

    containment 类型:选择器或元素或字符串或数组,默认值:false

    将拖动限制在指定元素或区域的范围内。 支持多种类型:

    • 选择器: 可拖动元素将包含在选择器找到的第一个元素的边界框内。如果未找到任何元素,则不会设置包含。
    • 元素:可拖动元素将包含在该元素的边界框内。
    • 字符串: 可能的值:"parent""document""window"
    • 数组:[ x1, y1, x2, y2 ] 形式定义边界框的数组。

    参考:http://api.jqueryui.com/draggable/

    因此这意味着您需要创建复杂的框或在您的drag 回调中构建碰撞检测。当drag 被触发时,它会传递一个eventui 对象。 ui.position 可以被操纵:

    帮助器的当前 CSS 位置为 { top, left } 对象。可以更改这些值以修改元素的放置位置。这对于自定义包含、捕捉等很有用。

    这可能很困难,所以如果这是一个初期项目或其他小项目,请考虑使用 Collision 插件:jQuery Dragging With Collision Detection

    考虑以下原始示例。

    $(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>

    这是一个使用一些 2D 碰撞检测的非常基本的示例。这不是很好,可以改进,但你可以看到从哪里开始。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2011-03-15
      • 2013-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多