将 "nephew" draggable 拖动到 "aunt" droppable,同时保持 CSS 和尺寸

Drag a "nephew" draggable to an "aunt" droppable while maintaining CSS and dimensions

我想将某个父项中的可拖动 #red 嵌套 拖动到某个可放置的 #green,它位于 div结构。

div 的尺寸需要用 percent 表示(响应),顶层 div 必须是 position: relative;,这可能让事情变得更复杂。

为了比较,这一切都适用于更简单的情况,其中 draggable #blue 和 droppable #green 是兄弟元素,但在 "nephew" 场景中中断(#red #green).

我明白我需要:

到目前为止一切顺利。

还有一个皱纹:侄子被拖的时候,它会往旁边跳,永远掉不下来

这是怎么回事?

  $(function() {
    $("#blue").draggable({
      snap: ".hexagon",
      snapMode: "inner",
      snapTolerance: 20,
      opacity: 0.7,
      addClasses: true,
      // stack: ".item",
      revert: "invalid"
    });
    $("#red").draggable({
      snap: ".hexagon",
      snapMode: "inner",
      snapTolerance: 20,
      opacity: 0.7,
      addClasses: true,
      // stack: ".item",
      revert: "invalid",
      appendTo: "body",
      helper: "clone",
    });
    $("#green").droppable({
      accept: ".hexagon",
      tolerance: "fit",
      drop: function(event, ui) {
        $(this)
          .addClass("ui-state-highlight")
          .find("span")
          .html("Dropped!");
      }
    });
  });
.hexagon {
    width: 20%;
    padding-top: 25%;
    overflow: hidden;
    -webkit-clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
    clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
    -webkit-shape-outside: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
    float: left;
    position: relative;
    z-index: 1;
  }

  .outer {
    position: relative;
    z-index: 0;
  }

  .inner {
    background-color: red;
    z-index: 9999;
    position: absolute;
    margin: 0 auto;
    width: 100%;
    top: 0;
    bottom: 0;
  }

  .textstyle {
    color: white;
    font-family: sans-serif;
    top: 25%;
    left: 10%;
    right: 10%;
    bottom: 10%;
    text-align: center;
    position: absolute;
    font-size: 1vw;
  }

  .green {
    background-color: green;
    z-index: 1000;
  }

  .blue {
    background-color: blue;
  }

  .red {
    background-color: red;
  }

  .ui-draggable-dragging {
    position: relative;
    padding-top: 25%;
    width: 20%;
  }
<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="green" class="hexagon outer green">
    <span class="textstyle">
            I am the dropzone.
          </span>
  </div>
  <div id="blue" class="hexagon outer blue">
    <span class="textstyle">
            I drag just fine, because I'm just a sibling element.
    </span>
  </div>
  <div class="hexagon outer">
    <div id="red" class="hexagon inner red">
      <span class="textstyle">
            I am nested, and I make a mess when dragged.
            I am the nephew.
      </span>
    </div>
  </div>

为什么分身会跳?

似乎 jQuery 可拖动插件正在通过强制 .ui-draggable-draggingposition: relative; 该插件实际上是将克隆相对于元素最初在页面上的位置定位在左侧。

要修复此行为,请向克隆添加覆盖以绝对定位它:

.red.ui-draggable-dragging {
    position: absolute;
    bottom: auto;
}

此外,添加 bottom: auto; 以覆盖 .inner 设置的 bottom 值,因为这会导致克隆拉伸。

为什么不能删除克隆?

这是因为 tolerance: "fit" 根据文档:

"fit": Draggable overlaps the droppable entirely.

可放置小部件 - (https://api.jqueryui.com/droppable/#option-tolerance)

这仍然会导致问题,因为克隆是绝对定位的,因为它的 width 未计算为与原始 .hexagon 相同(原始的 width: 20%; 是根据body 宽度,而克隆的 width: 20%; 是根据视口计算的)。为了缓解这种情况,body 上的默认浏览器 margin 已被抑制(尽管这也可以通过将 .hexagon 包装在容器中来解决)。

如果拖动动作不需要很精确tolerance: "fit"可以改成tolerance: "intersect"这样可以留出更多余地

$(function() {
  $("#blue").draggable({
    snap: ".hexagon",
    snapMode: "inner",
    snapTolerance: 20,
    opacity: 0.7,
    addClasses: true,
    // stack: ".item",
    revert: "invalid"
  });
  $("#red").draggable({
    snap: ".hexagon",
    snapMode: "inner",
    snapTolerance: 20,
    opacity: 0.7,
    addClasses: true,
    // stack: ".item",
    revert: "invalid",
    appendTo: "body",
    helper: "clone"
  });
  $("#green").droppable({
    accept: ".hexagon",
    tolerance: "fit",
    drop: function(event, ui) {
      $(this)
        .addClass("ui-state-highlight")
        .find("span")
        .html("Dropped!");
    }
  });
});
body {
  margin: 0;
}

.hexagon {
  width: 20%;
  padding-top: 25%;
  overflow: hidden;
  -webkit-clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  -webkit-shape-outside: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  float: left;
  position: relative;
  z-index: 1;
}

.outer {
  position: relative;
  z-index: 0;
}

.inner {
  background-color: red;
  z-index: 9999;
  position: absolute;
  margin: 0 auto;
  width: 100%;
  top: 0;
  bottom: 0;
}

.textstyle {
  color: white;
  font-family: sans-serif;
  top: 25%;
  left: 10%;
  right: 10%;
  bottom: 10%;
  text-align: center;
  position: absolute;
  font-size: 1vw;
}

.green {
  background-color: green;
  z-index: 1000;
}

.blue {
  background-color: blue;
}

.red {
  background-color: red;
}

.ui-draggable-dragging {
  position: relative;
  padding-top: 25%;
  width: 20%;
}

.red.ui-draggable-dragging {
  position: absolute;
  bottom: auto;
}
<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="green" class="hexagon outer green">
  <span class="textstyle">
            I am the dropzone.
          </span>
</div>
<div id="blue" class="hexagon outer blue">
  <span class="textstyle">
            I drag just fine, because I'm just a sibling element.
    </span>
</div>
<div class="hexagon outer">
  <div id="red" class="hexagon inner red">
    <span class="textstyle">
            I am nested, and I make a mess when dragged.
            I am the nephew.
      </span>
  </div>
</div>