You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用interact.js拖拽时动态创建/移动放置区域的问题及优化咨询

interact.js拖拽时动态创建/移动放置区域的问题及优化咨询

我正在开发一个使用interact.js实现拖拽(DND)功能的应用。通常拖拽交互开始后,页面会发生一些变化:放置区(dropzones)位置改变、被删除,或者新的放置区被创建。

Creation (main issue)

在下面的代码片段中,当你将可拖拽元素悬停在橙色盒子上时,会生成新的放置区,但这些新放置区要等到你放下并重新拿起可拖拽元素后才会激活。

// DRAGGABLE
const draggable = document.getElementById("draggable");
let x = 0;
let y = 0;
interact(draggable).draggable({
  autoScroll: false,
  onmove(e) {
    x += e.dx;
    y += e.dy;
    // translate the element
    draggable.style.transform = "translate(" + x + "px, " + y + "px)";
  }
});

// HOVERZONE
const hoverzone = document.getElementById("hoverzone");
setupDropzone(hoverzone, addNewZone);

// ADDED ZONES
function addNewZone() {
  // Make html element
  const node = document.createElement("div");
  node.classList.add("box", "zone");
  const textNode = document.createTextNode("Hi!");
  node.appendChild(textNode);
  document.body.appendChild(node);
  // Ininialize interactable
  setupDropzone(node);
}

// HELPER
function setupDropzone(element, ondragenter = () => {}) {
  interact(element).dropzone({
    accept: "#draggable",
    ondrop(e) {
      element.classList.remove("drag-hover");
    },
    ondragenter(e) {
      element.classList.add("drag-hover");
      ondragenter();
    },
    ondragleave(e) {
      element.classList.remove("drag-hover");
    }
  });
}
body {
  display: flex;
}

.box {
  width: 120px;
  border-radius: 8px;
  padding: 20px;
  margin: 1rem;
  background-color: peru;
  color: white;

  touch-action: none;
  user-select: none;

  box-sizing: border-box;
}

#draggable {
  background-color: #29e;
  z-index: 99;
}

.zone {
  background-color: pink;
}

.drag-hover {
  outline: 3px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/interact.js/1.10.27/interact.min.js"></script>

<div class="box" id="hoverzone">
  Hover draggable on me!
</div>

<div class="box" id="draggable">
  Drag me!
</div>

我曾经尝试过在新放置区中使用event.interaction.start(...),通过保存可拖拽元素的dragstart事件来实现,但这只会把事情搞砸,没有任何进展。

我也找不到在dragstart之后延迟DND流程(比如矩形计算、在放置区触发dragactivate等)的方法,直到新放置区初始化完成。

请问有没有基于interact.js的解决方案,或者有没有类似的拖拽库可以优雅地解决这个问题以及下面提到的问题?


Movement (solved but worth mentioning)

我用interact.dynamicDrop(true);解决了放置区移动的问题,但这个方案并不理想,因为它会在每次dragmove时重新计算矩形,而我的应用中放置区实际上很少移动。有没有办法只触发一次重计算?我之前试过下面的方法,但这让我的代码变得复杂,而且感觉太不优雅:

  • 启用dynamicDrop
  • 等待dragmove触发
  • 禁用dynamicDrop

备注:内容来源于stack exchange,提问作者t42

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 18:24:31