无法使用 interact.js 拖放到另一个 div

Can't drag and drop to another div using interact.js

Html/css新手,

我正在使用 interact.js 来达到一定的 UI,我可以将列表中的项目放入放置区。问题是我的列表可能会变得很长,我需要向列表添加滚动条,当我尝试这样做时,我创建了一个 'div' 并将列表项放入其中以显示滚动行为。

但是当我将列表项放在 div 中并将放置区放在它外面时,这些项目不会被放置在那里并且列表显示出一种奇怪的行为,所有这些都开始堆叠在上面底部列表项(位于 div 包含项的底部)。

这是我的 html:

<div class="items">
    <p style="padding-top: 20px; font-size:18px">Stacked Items</p>
    <div style = "height: 400px; overflow: scroll">
      <div id="itemstodrop" class="drag-drop"> item 1 </div>
      <div id="itemstodrop" class="drag-drop"> item 2 </div>
      <div id="itemstodrop" class="drag-drop"> item 3 </div>
      <div id="itemstodrop" class="drag-drop"> item 4 </div>
      <div id="itemstodrop" class="drag-drop"> item 5 </div>
      <div id="itemstodrop" class="drag-drop"> item 6 </div>
      <div id="itemstodrop" class="drag-drop"> item 7 </div>
      <div id="itemstodrop" class="drag-drop"> item 8 </div>
      <div id="itemstodrop" class="drag-drop"> item 9 </div>
      <div id="itemstodrop" class="drag-drop"> item 10 </div>
      <div id="itemstodrop" class="drag-drop"> item 11 </div>
      <div id="itemstodrop" class="drag-drop"> item 12 </div>
    </div>
    <div id="inner-dropzone" class="dropzone">Drop here</div>
</div>

这是我的脚本,其中包含 interact.js 代码:

import interact from 
'https://cdn.jsdelivr.net/npm/@interactjs/interactjs/index.js'
// enable draggables to be dropped into this

var startPos = null;
//define the initial position for each rig tile.
function dragMoveListener (event) {

  var target = event.target
  // keep the dragged position in the data-x/data-y attributes
  var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx
  var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy

  // translate the element
  target.style.webkitTransform =
    target.style.transform =
      'translate(' + x + 'px, ' + y + 'px)'

  // update the posiion attributes
  target.setAttribute('data-x', x)
  target.setAttribute('data-y', y)
}

// this function is used later in the resizing and gesture demos
window.dragMoveListener = dragMoveListener


//ALL THE FUNCTIONS BELOW TALK ABOUT THE DRAGGABLE AREA.
interact('.dropzone').dropzone({
  // only accept elements matching this CSS selector
  accept: '#itemstodrop',
  // the item should go 100% inside the draggable area...
  overlap: 0.9999999, //somehow it does not take the value 100%

  // listen for drop related events:

  ondropactivate: function (event) {
    // add active dropzone feedback
    event.target.classList.add('drop-active')
  },
  ondragenter: function (event) {

    //when item enters the draggable area
    var draggableElement = event.relatedTarget
    var dropzoneElement = event.target

    console.log(draggableElement.firstChild.nodeValue);
    // feedback the possibility of a drop
    dropzoneElement.classList.add('drop-target')
    draggableElement.classList.add('can-drop')

  },
  ondragleave: function (event) {


    console.log(startPos)
    event.draggable.draggable({
        snap: {
        targets: [startPos]
        }
    });

    //when item leaves the draggable area
    // remove the drop feedback style
    event.target.classList.remove('drop-target')
    event.relatedTarget.classList.remove('can-drop')

  },
  ondrop: function (event) {

    //when the item is droppd in the draggable area
    {% comment %} event.relatedTarget.textContent = 'Dropped' {% endcomment %}
  },
  ondropdeactivate: function (event) {
    // remove active dropzone feedback
    event.target.classList.remove('drop-active')
    event.target.classList.remove('drop-target')
  }
})

interact('.drag-drop')
  .draggable({
    inertia: true,
    modifiers: [
      interact.modifiers.restrictRect({
        restriction: 'parent',
        endOnly: true
      })
    ],
    autoScroll: true,
    // dragMoveListener from the dragging demo above
    listeners: { move: dragMoveListener }
  })
</script>

这是渲染时的样子:(基本上不能将任何物品放到掉落区域。)

演示的完整工作页面: (我添加了一条评论,告诉我把 div 放在哪里了。)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
#outer-dropzone {
  height: 140px;
}

#inner-dropzone {
  height: 80px;
}

.dropzone {
  background-color: #ccc;
  border: dashed 4px transparent;
  border-radius: 4px;
  margin: 10px auto 30px;
  padding: 10px;
  width: 80%;
  transition: background-color 0.3s;
}

.drop-active {
  border-color: #aaa;
}

.drop-target {
  background-color: #29e;
  border-color: #fff;
  border-style: solid;
}

.drag-drop {
  display: inline-block;
  min-width: 40px;
  padding: 2em 0.5em;

  color: #fff;
  background-color: #29e;
  border: solid 2px #fff;

  touch-action: none;
  -webkit-transform: translate(0px, 0px);
          transform: translate(0px, 0px);

  transition: background-color 0.3s;
}

.drag-drop.can-drop {
  color: #000;
  background-color: #4e4;
}
</style>
</head>
<body>
{% comment %} I NEED THIS DIV UNDER THIS COMMENT, TO ADD A SCROLL AREA. BUT WHEN I GIVE THIS DIV, THE DROP DOES  NOT OCCUR. {% endcomment %}
  <div> 
    <div id="no-drop" class="drag-drop"> #no-drop </div>
    <div id="yes-drop" class="drag-drop"> #yes-drop </div>
  </div>

  <div id="outer-dropzone" class="dropzone">
  #outer-dropzone
  <div id="inner-dropzone" class="dropzone">#inner-dropzone</div>
 </div>



<script type="module">
import interact from 
'https://cdn.jsdelivr.net/npm/@interactjs/interactjs/index.js'
// enable draggables to be dropped into this


interact('.draggable')
  .draggable({
    // enable inertial throwing
    inertia: true,
    // keep the element within the area of it's parent
    modifiers: [
      interact.modifiers.restrictRect({
        restriction: 'parent',
        endOnly: true
      })
    ],
    // enable autoScroll
    autoScroll: true,

    listeners: {
      // call this function on every dragmove event
      move: dragMoveListener,

      // call this function on every dragend event
      end (event) {
        var textEl = event.target.querySelector('p')

        textEl && (textEl.textContent =
          'moved a distance of ' +
          (Math.sqrt(Math.pow(event.pageX - event.x0, 2) +
                     Math.pow(event.pageY - event.y0, 2) | 0))
            .toFixed(2) + 'px')
      }
    }
  })

function dragMoveListener (event) {
  var target = event.target
  // keep the dragged position in the data-x/data-y attributes
  var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx
  var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy

  // translate the element
  target.style.webkitTransform =
    target.style.transform =
      'translate(' + x + 'px, ' + y + 'px)'

  // update the posiion attributes
  target.setAttribute('data-x', x)
  target.setAttribute('data-y', y)
}

// this function is used later in the resizing and gesture demos
window.dragMoveListener = dragMoveListener


//ALL THE FUNCTIONS BELOW TALK ABOUT THE DRAGGABLE AREA.
interact('.dropzone').dropzone({
  // only accept elements matching this CSS selector
  accept: '#yes-drop',
  // the item should go 100% inside the draggable area...
  overlap: 0.9999999, //somehow it does not take the value 100%

  // listen for drop related events:

  ondropactivate: function (event) {
    // add active dropzone feedback
    event.target.classList.add('drop-active')
  },
  ondragenter: function (event) {

    //when item enters the draggable area
    var draggableElement = event.relatedTarget
    var dropzoneElement = event.target

    console.log(draggableElement.firstChild.nodeValue);
    // feedback the possibility of a drop
    dropzoneElement.classList.add('drop-target')
    draggableElement.classList.add('can-drop')

  },
  ondragleave: function (event) {




    //when item leaves the draggable area
    // remove the drop feedback style
    event.target.classList.remove('drop-target')
    event.relatedTarget.classList.remove('can-drop')

  },
  ondrop: function (event) {

    //when the item is droppd in the draggable area
    {% comment %} event.relatedTarget.textContent = 'Dropped' {% endcomment %}
  },
  ondropdeactivate: function (event) {
    // remove active dropzone feedback
    event.target.classList.remove('drop-active')
    event.target.classList.remove('drop-target')
  }
})

interact('.drag-drop')
  .draggable({
    inertia: true,
    modifiers: [
      interact.modifiers.restrictRect({
        restriction: 'parent',
        endOnly: true
      })
    ],
    autoScroll: true,
    // dragMoveListener from the dragging demo above
    listeners: { move: dragMoveListener }
  })
</script>
</body>
</html>

您需要将 accept: '#rigstodrop' 更改为 accept: '#itemstodrop',因为此处您的 div 具有您需要拖放的 ID itemstodrop。另外,使用 restriction: '.items' 来限制 rect 不能超出那个区域。

演示代码 :

var startPos = null;
//define the initial position for each rig tile.
function dragMoveListener(event) {

  var target = event.target
  // keep the dragged position in the data-x/data-y attributes
  var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx
  var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy

  // translate the element
  target.style.webkitTransform =
    target.style.transform =
    'translate(' + x + 'px, ' + y + 'px)'

  // update the posiion attributes
  target.setAttribute('data-x', x)
  target.setAttribute('data-y', y)
}

// this function is used later in the resizing and gesture demos
window.dragMoveListener = dragMoveListener
interact('.dropzone').dropzone({
  // only accept elements matching this CSS selector
  accept: '#itemstodrop', //change this
  // the item should go 100% inside the draggable area...
  overlap: 0.9999999,
  ondropactivate: function(event) {
    // add active dropzone feedback
    event.target.classList.add('drop-active')
  },
  ondragenter: function(event) {

    //when item enters the draggable area
    var draggableElement = event.relatedTarget
    var dropzoneElement = event.target

    console.log(draggableElement.firstChild.nodeValue);
    // feedback the possibility of a drop
    dropzoneElement.classList.add('drop-target')
    draggableElement.classList.add('can-drop')

  },
  ondragleave: function(event) {


    console.log(startPos)
    event.draggable.draggable({
      snap: {
        targets: [startPos]
      }
    });

    //when item leaves the draggable area
    // remove the drop feedback style
    event.target.classList.remove('drop-target')
    event.relatedTarget.classList.remove('can-drop')

  },
  ondrop: function(event) {

    //when the item is droppd in the draggable area
    event.relatedTarget.textContent = 'Dropped'
  },
  ondropdeactivate: function(event) {
    // remove active dropzone feedback
    event.target.classList.remove('drop-active')
    event.target.classList.remove('drop-target')
  }
})

interact('.drag-drop')
  .draggable({
    inertia: true,
    modifiers: [
      interact.modifiers.restrictRect({
        restriction: '.items', //change this
        endOnly: true
      })
    ],
    autoScroll: true,
    // dragMoveListener from the dragging demo above
    listeners: {
      move: dragMoveListener
    }
  })
.itemstodrop {
  touch-action: none;
  user-select: none;
}


#inner-dropzone {
  height: 80px;
}

.dropzone {
  background-color: #ccc;
  border: dashed 4px transparent;
  border-radius: 4px;
  margin: 10px auto 30px;
  padding: 10px;
  width: 80%;
  transition: background-color 0.3s;
}

.drop-active {
  border-color: #aaa;
}

.drop-target {
  background-color: #29e;
  border-color: #fff;
  border-style: solid;
}

.drag-drop {
  display: inline-block;
  min-width: 40px;
  padding: 2em 0.5em;
  color: #fff;
  background-color: #29e;
  border: solid 2px #fff;
  touch-action: none;
  -webkit-transform: translate(0px, 0px);
  transform: translate(0px, 0px);
  transition: background-color 0.3s;
}

.drag-drop.can-drop {
  color: #000;
  background-color: #4e4;
}
<script src="https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js"></script>
<div class="items">
  <p style="padding-top: 20px; font-size:18px">Stacked Rigs</p>
  <div style="height: auto;overflow: scroll">
    <div id="itemstodrop" class="drag-drop itemstodrop"> item 1 </div>
    <div id="itemstodrop" class="drag-drop itemstodrop"> item 2 </div>
    <div id="itemstodrop" class="drag-drop itemstodrop"> item 3 </div>
    <div id="itemstodrop" class="drag-drop itemstodrop"> item 4 </div>
    <div id="itemstodrop" class="drag-drop itemstodrop"> item 5 </div>
    <div id="itemstodrop" class="drag-drop itemstodrop"> item 6 </div>
    <div id="itemstodrop" class="drag-drop itemstodrop"> item 7 </div>
    <div id="itemstodrop" class="drag-drop itemstodrop"> item 8 </div>
    <div id="itemstodrop" class="drag-drop itemstodrop"> item 9 </div>
    <div id="itemstodrop" class="drag-drop itemstodrop"> item 10 </div>
    <div id="itemstodrop" class="drag-drop itemstodrop"> item 11 </div>
    <div id="itemstodrop" class="drag-drop itemstodrop"> item 12 </div>
    <!--put this inside div-->
    <div id="inner-dropzone" class="dropzone">Drop here</div>
  </div>




</div>