HTML5 拖放 - 仅在每个拖放区的项目上

Posted

技术标签:

【中文标题】HTML5 拖放 - 仅在每个拖放区的项目上【英文标题】:HTML5 drag and drop - Only on item per dropzone 【发布时间】:2019-04-03 15:50:08 【问题描述】:

我有一些 div 作为 dropzones 和一些作为可拖动对象。

<div class="container">
   <div class="drop"></div>
   <div class="drop"></div>
   <div class="drop"></div>
</div>
<div class="container">
    <div class="drag" id="drag-a" draggable="true">box a</div>
    <div class="drag" id="drag-b" draggable="true">box b</div>
    <div class="drag" id="drag-c" draggable="true">box c</div>
</div>
<style>
.drop 
    border: 1px solid #000;
    height: 40px;
    margin: 5px;
    width: 200px;

.drag 
    background: #000;
    color: #fff;
    display: inline-block;
    margin: 5px;
    padding: 5px;
    user-select: none;

</style>
<script>
$(document).ready(function () 
    $('.drop').on('dragover', function(e)
        e.preventDefault();
    );
    $('.drag').on('dragstart', function(e) 
        e.originalEvent.dataTransfer.setData('Text', e.target.id);
    );
    $('.drop').on('drop', function(e) 
        e.preventDefault();
        var data = e.originalEvent.dataTransfer.getData('Text');  
        e.target.appendChild(document.getElementById(data));
    );
);
</script>

使用原生 html5 拖放和 jQuery 可以正常工作。现在我想将放置区限制为一个项目。应该不可能把另一个放到这个区域,但我不知道怎么做。

这两个可拖动的框有没有可能交换位置?

【问题讨论】:

【参考方案1】:

您只需要删除该元素的事件处理程序,在 jQuery 中您可以使用 `.off() 来完成。

$('.drop').on('drop', function(e) 
    e.preventDefault();
    var data = e.originalEvent.dataTransfer.getData('Text');  
    e.target.appendChild(document.getElementById(data));
    // add this line
    $(this).off('dragover drop');
);

$(document).ready(function () 
    $('.drop').on('dragover', function(e)
        e.preventDefault();
    );
    $('.drag').on('dragstart', function(e) 
        e.originalEvent.dataTransfer.setData('Text', e.target.id);
    );
    $('.drop').on('drop', function(e) 
        e.preventDefault();
        var data = e.originalEvent.dataTransfer.getData('Text');  
        e.target.appendChild(document.getElementById(data));
        $(this).off('dragover drop');
    );
);
.drop 
    border: 1px solid #000;
    height: 40px;
    margin: 5px;
    width: 200px;

.drag 
    background: #000;
    color: #fff;
    display: inline-block;
    margin: 5px;
    padding: 5px;
    user-select: none;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
   <div class="drop"></div>
   <div class="drop"></div>
   <div class="drop"></div>
</div>
<div class="container">
    <div class="drag" id="drag-a" draggable="true">box a</div>
    <div class="drag" id="drag-b" draggable="true">box b</div>
    <div class="drag" id="drag-c" draggable="true">box c</div>
</div>

重新启动拖放功能

即使您将每个放置区限制为仅一个框,也是允许用户移除已放置的框并放置不同的框的常见情况。

首先,您应该在命名函数声明中转换匿名函数处理程序,以便能够重用它们。

然后,让盒子容器接受拖放操作。

最后,当用户在容器中放置一个盒子时,在任何空的放置区域中再次添加 dropdragover 事件的处理程序。

注意:这一次,我稍微修改了类的名称,使其更清晰。

var dragOverHandler = function(e) 
  e.preventDefault();
;
var dropOnDropZoneHandler = function(e) 
  e.preventDefault();
  var data = e.originalEvent.dataTransfer.getData('Text');
  e.target.appendChild(document.getElementById(data));
  $(this).off('dragover drop');
;
var dropOnBoxContainerHandler = function(e) 
  e.preventDefault();
  var data = e.originalEvent.dataTransfer.getData('Text');
  e.target.appendChild(document.getElementById(data));
  $('.dropzone').each(function() 
    if ($(this).is(':empty')) 
      $(this).on('dragover', dragOverHandler);
      $(this).on('drop', dropOnDropZoneHandler);
    
  );


$(document).ready(function() 
  $('.box').on('dragstart', function(e) 
    e.originalEvent.dataTransfer.setData('Text', e.target.id);
  );
  $('.dropzone, #boxContainer').on('dragover', dragOverHandler);
  $('.dropzone').on('drop', dropOnDropZoneHandler);
  $('#boxContainer').on('drop', dropOnBoxContainerHandler);
);
.dropzone, #boxContainer 
  border: 1px solid #000;
  height: 40px;
  margin: 5px;
  width: 200px;


.box 
  background: #000;
  color: #fff;
  display: inline-block;
  margin: 5px;
  padding: 5px;
  user-select: none;


#boxContainer 
  background-color: #AAA;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <div class="dropzone"></div>
  <div class="dropzone"></div>
  <div class="dropzone"></div>
</div>
<div id="boxContainer">
  <div class="box" id="drag-a" draggable="true">box a</div>
  <div class="box" id="drag-b" draggable="true">box b</div>
  <div class="box" id="drag-c" draggable="true">box c</div>
</div>

【讨论】:

谢谢,太完美了。是否可以再次开始拖动/拖动?

以上是关于HTML5 拖放 - 仅在每个拖放区的项目上的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 拖放 getData() 仅适用于 Chrome 中的拖放事件?

HTML5 拖放 getData() 仅适用于 Chrome 中的拖放事件?

Angular 7 拖放 - 动态创建拖放区

如何使用angularJS突出显示可拖动元素下的拖放区?

上传文件时检测到取消的拖放操作

可拖放 可拖动 附加到位置