当它已经有子元素时防止丢弃事件?拖放

时间:2018-06-02 19:49:54

标签: javascript jquery html5 drag-and-drop

我正在做简单的匹配游戏。游戏有很多问题。我正在使用拖放进行匹配。首先,我将图像元素放到一个容器中,当我选择另一个元素并尝试将其放入同一个容器时,目前它正在覆盖现有元素。我想检查已经有元素的容器。如果没有,则允许掉落,否则防止跌落。

代码:

{{1}}

屏幕截图

For Reference

当容器已经有子元素时,我想阻止drop事件。同时,当任何一个容器为空交换时,我需要重新排列掉落的元素。

实际上我想将图像从左容器拖到右容器。在将元素放到右侧容器之前,我想检查容器是否已经有另一个之前丢失的图像。如果容器中没有图像,则允许放下图像,否则防止丢失图像。

等待建议。提前致谢!

2 个答案:

答案 0 :(得分:4)

我认为你可以检查元素之间的冲突并决定你的行动

按照示例链接查看是否存在使用vanilla javascript和jquery的冲突:

Vanilla JS Div Collision Detection

How to detect div collision in my case?

https://jsfiddle.net/jeanwfsantos/bp57zgrL/

<style>
#div1 {
  width: 100px;
  height: 100px;
  border: 1px solid #aaaaaa;
  padding: 10px;
}

.element {
  width: 100px;
  height: 100px;
}
</style>
<div 
  id="div1" 
  ondrop="drop(event)" 
  ondragover="allowDrop(event)"></div>
<div
     class="element"
     id="drag1"
     style="background: blue;"
     draggable="true"
     ondragstart="drag(event)"
     ondrag="dragMove(event)"></div>
<div
     class="element"
     id="drag2"
     style="background: red;"
     draggable="true"
     ondragstart="drag(event)"
     ondrag="dragMove(event)"></div>

<script>
const elements = document.querySelectorAll('.element')
let hasCollision = false
let offset = [0, 0]

function allowDrop(ev) {
  ev.preventDefault()
}

function drag(ev) {
  ev.dataTransfer.setData('text', ev.target.id)
  offset = [
    ev.target.offsetLeft - ev.clientX,
    ev.target.offsetTop - ev.clientY
  ]
}

function drop(ev) {
  ev.preventDefault()
  const data = ev.dataTransfer.getData('text')
  if (!hasCollision) {
    ev.target.appendChild(document.getElementById(data))
  }
}

function dragMove(e) {
  hasCollision = Array.prototype.some.call(elements, d => {
    if (d.id !== e.target.id) {
      return isCollide(e, d)
    }
    return false
  })
}

function isCollide(a, b) {
  const aRect = a.target.getBoundingClientRect()
  const bRect = b.getBoundingClientRect()
  return !(
    ((a.clientY + offset[1] + aRect.height) < (bRect.top)) ||
    (a.clientY + offset[1] > (bRect.top + bRect.height)) ||
    ((a.clientX + offset[0] + aRect.width) < bRect.left) ||
    (a.clientX + offset[0] > (bRect.left + bRect.width))
  )
}
</script>

我希望这会对你有所帮助。

答案 1 :(得分:3)

我认为您真正的问题是您已将allowDrop(event)实施为event.preventDefault(),因此总是允许丢弃。

相反,您想要做的是在目标已被占用的情况下禁止丢弃。尝试使用allowDrop()的以下实现:

function allowDrop(event) {
    var t = event.target;
    // Find the drop target
    while (t !== null && !t.classList.contains("target")) {
        t = t.parentNode;
    }
    // If the target is empty allow the drop.
    if (t && t.childNodes.length == 0) {
        event.preventDefault();
    }
    return false;
}

这里有一个fiddle,可以显示它的实际效果。 (我自由地承认我是根据之前的答案借来的。:)

&#13;
&#13;
let offset = [0, 0]

function allowDrop(ev) {
  var t = ev.target;
  while (t !== null && !t.classList.contains("target")) {
    t = t.parentNode;
  }
  if (t && t.childNodes.length > 0) {
    return false;
  }
  ev.preventDefault()
}

function drag(ev) {
  ev.dataTransfer.setData('dragID', ev.target.id)
  offset = [
    ev.target.offsetLeft - ev.clientX,
    ev.target.offsetTop - ev.clientY
  ]
}

function drop(ev) {
  ev.preventDefault()
  const data = ev.dataTransfer.getData('dragID')
  ev.target.appendChild(document.getElementById(data))
}
&#13;
.target {
  width: 100px;
  height: 100px;
  border: 1px solid #aaaaaa;
  padding: 10px;
}

.element {
  width: 100px;
  height: 100px;
}
&#13;
<div class="target" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="element" id="drag1" style="background: blue;" draggable="true" ondragstart="drag(event)"></div>
<div class="element" id="drag2" style="background: red;" draggable="true" ondragstart="drag(event)"></div>
&#13;
&#13;
&#13;