简体   繁体   中英

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

Html/css newbie here,

I am using interact.js to attain a certain UI where I can drop items from a list into a drop zone. The problem is my list can grow very long and I need to add scroll to the list, and when I try to do so I have create a 'div' and put the list items into it to show the scroll behaviour.

But when I put the list items inside a div and the drop zone outside it, the items do not get dropped there and the list shows a weird behaviour, all of them starts getting stacked on top of the bottom list item (at the bottom of the div containing the items).

This is my 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>

This is my script which holds interact.js code:

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>

This is how it looks when rendered: (Basically can't drop any item to drop area.)

在此处输入图像描述

Full working page for demo: (I have added a comment which tells where have I put the 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>

You need to change accept: '#rigstodrop' to accept: '#itemstodrop' because here your div has id itemstodrop which you need to drag and drop. Also, use restriction: '.items' to restrict rect not to go beyond that area.

Demo code :

 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM