html5拖放drop:无法可靠地检测到用户正在拖动元素

时间:2016-11-24 12:24:26

标签: javascript html5 drag-and-drop

function handleDragStart(e) {
  this.style.opacity = '0.4';  // this / e.target is the source node.
}

function handleDragOver(e) {
  if (e.preventDefault) {
    e.preventDefault(); // Necessary. Allows us to drop.
  }

  e.dataTransfer.dropEffect = 'move';  // See the section on the DataTransfer object.

  return false;
}

function handleDragEnter(e) {
  // this / e.target is the current hover target.
  this.classList.add('over');
  console.debug("dragEnterTarget",e.target);
}

function handleDragLeave(e) {
  this.classList.remove('over');  // this / e.target is previous target element.
  console.debug("dragLeaveTarget",e.target);
}

function handleDrop(e) {
  // this / e.target is current target element.

  if (e.stopPropagation) {
    e.stopPropagation(); // stops the browser from redirecting.
  }

  // See the section on the DataTransfer object.

  return false;
}

function handleDragEnd(e) {
  // this/e.target is the source node.
  this.style.opacity = '1';
  [].forEach.call(cols, function (col) {
    col.classList.remove('over');
  });
}

var cols = document.querySelectorAll('#columns .column');
[].forEach.call(cols, function(col) {
  col.addEventListener('dragstart', handleDragStart, false);
  col.addEventListener('dragenter', handleDragEnter, false);
  col.addEventListener('dragover', handleDragOver, false);
  col.addEventListener('dragleave', handleDragLeave, false);
  col.addEventListener('drop', handleDrop, false);
  col.addEventListener('dragend', handleDragEnd, false);
});
[draggable] {
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  user-select: none;
  /* Required to make elements draggable in old WebKit */
  -khtml-user-drag: element;
  -webkit-user-drag: element;
}

#columns {
  display: flex;
}

.column {
  margin: 10px;
  width: 200px;
  height: 200px;
  display: flex;
  flex-direction: column;
}

.column > * {
  border: solid;
  flex-grow: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.column.over > * {
  border: solid green;
}
<div id="columns">
  <div class="column" draggable="true">
    <div>
      A1
    </div>
    <div>
      A2
    </div>
    <div>
      A3
    </div>
  </div>
  <div class="column" draggable="true">
    <div>
      B1
    </div>
    <div>
      B2
    </div>
    <div>
      B3
    </div>
  </div>
    <div class="column" draggable="true">
    <div>
      C1
    </div>
    <div>
      C2
    </div>
    <div>
      C3
    </div>
  </div>
</div>

我是新手,拖放并遵循本教程:https://www.html5rocks.com/en/tutorials/dnd/basics/

本教程工作正常,但在其中,drop目标非常简单。

如果放置目标实际上是一个更复杂的html元素组合怎么办?

我注意到以下两种行为(至少在最近的Chrome中):

  • dragEnter / dragLeave也可以触发嵌套的html元素,因此仅依靠dragLeave事件来确定用户是否正在停止拖动操作似乎不可靠
  • dragEnter / dragLeave可能无法为树中的所有中间节点触发:如果在父节点上设置onDragEnter,则您收到的第一个dragEnter事件可能没有event.target === parent(例如,如果鼠标直接进入内部,则会发生一个孩子在输入父母时),所以使用event.target进行过滤可能在所有情况下都不可靠

这是一个JsFiddle演示,使用与教程大致相同的结构,但具有更复杂的放置目标

https://jsfiddle.net/asct3gLj/

正如您所看到的,当用户将一列拖到另一列之上时,我无法可靠地设置.over类。有人可以找到一个解决方案,不需要更改html标记吗?

0 个答案:

没有答案