JS实现拖曳排序效果并输出新的排序结果

本篇,我们做个简单的鼠标拖拽排序的效果,看图说话:

这段代码实现了一个简单的拖曳排序功能。用户可以通过拖动列表中的项来重新排列它们。每次排序后,新的排序结果将输出到页面上的#output元素中。这个例子不包括任何错误处理,并且假设列表中的data-index属性反映了当前项在列表中的正确索引。在实际应用中,你可能需要添加更多的错误处理和复杂性来处理不同的边界情况。

简单的布局结构:

<div class="rank_wrap">
    <ul id="sortable-list">
      <li draggable="true" data-index="0">C++</li>
      <li draggable="true" data-index="1">PHP</li>
      <li draggable="true" data-index="2">python</li>
      <li draggable="true" data-index="3">Java</li>
      <li draggable="true" data-index="4">Swift</li>
    </ul>
    <div id="output" class="output"></div>
</div>

同样简单的CSS样式表:

.rank_wrap{
    position: fixed;
    width: 50%;
    height: auto;
    overflow: hidden;
    padding: 10px;
    /* 居中 */
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);  
}
#sortable-list {
  list-style-type: none;
  margin: 0;
  padding: 0;
  width: 100%;
  box-sizing: border-box;
}
 
#sortable-list li {
  background-color: #f9f9f9;
  border: 1px solid #ddd;
  margin: 5px;
  padding: 10px;
  cursor: move;
}
#sortable-list li:hover{
    background: #ffc;
}
.output{
    padding: 10px;
    color: #999;
    font-size: 14px;
}

接下来是解决问题的核心,选择->拖拽->释放、定位、输出排序

const list = document.getElementById('sortable-list');
const output = document.getElementById('output');
 
list.addEventListener('dragstart', (e) => {
  e.target.style.opacity = '0.6';
  e.dataTransfer.setData('text/plain', e.target.getAttribute('data-index'));
});
 
list.addEventListener('dragend', (e) => {
  e.target.style.opacity = '1';
});
 
list.addEventListener('dragover', (e) => {
  e.preventDefault();
  e.target.style.border = '1px dashed #ddd';
});
 
list.addEventListener('dragleave', (e) => {
  e.target.style.border = '';
});
 
list.addEventListener('drop', (e) => {
  e.preventDefault();
  const fromIndex = e.dataTransfer.getData('text/plain');
  const toIndex = Array.from(list.children).indexOf(e.target);
  moveItem(fromIndex, toIndex);
});
 
function moveItem(fromIndex, toIndex) {
  const items = Array.from(list.children);
  const draggedItem = items[fromIndex];
 
  items.splice(fromIndex, 1);
  items.splice(toIndex, 0, draggedItem);
 
  list.innerHTML = '';
  items.forEach((item, index) => {
    item.setAttribute('data-index', index);
    list.appendChild(item);
  });
 
  output.textContent = '新排序:' + items.map(item => item.textContent).join(', ');
}

这个例子使用了HTML5的 drag和 drop APIs,因为浏览器兼容问题,本例只做学习用。

相关知识拓展:

在html5之前,拖放远没有这么容易。感谢HTML5让网页元素支持 拖放。接下来,我们聊聊这个属性:draggable。关于它的详细资料可参考:w3school HTML5 拖放

首先,让元素支持拖动:

它的使用非常简单,你只要给网页中要拖放的元素增加简单的代码就可以实现。

<div class="text" draggable="true" >hello word</div>

draggable的属性有三个选项:

  • true:可以被拖放
  • false:不可以被拖放
  • auto:浏览器自己判断是否可以被拖放

而被拖放对象的事件,也有三种:

  • ondragstart——开始拖放
  • ondrag——拖放过程中
  • ondragend——结束拖放时

当拖放目标进入投放区,会产生四种事件:

  • ondragenter——被拖放元素鼠标进入时
  • ondragover——被拖放元素鼠标进入了
  • ondragleave——被拖放元素鼠标离开了
  • ondrop——被拖放元素放下了

传递拖拽数据

DataTransfer 对象在 HTML5 拖放 API 中使用,它代表了一种数据和这些数据的类型,可以在拖放操作中传递。

以下是一些使用 DataTransfer 对象的常见方法:

  1. setData(format, data): 设置数据和它的类型。format 参数通常是 "text" 或 "URL",data 参数是实际的数据。
  2. getData(format): 获取设置的数据。format 参数应与 setData 方法中使用的相同。
  3. clearData([format]): 清除数据。如果提供了 format 参数,则只清除该格式的数据;如果没有提供,则清除所有数据。
  4. setDragImage(imgElement, x, y): 设置一个图像元素作为拖动的可视反馈。imgElement 是要显示的图像,x 和 y 指定图像相对于鼠标指针的位置。

接下来看个简单的应用例子:

// 获取拖动的源元素
const dragSource = document.getElementById('dragSource');
 
// 设置拖动开始时的事件监听器
dragSource.addEventListener('dragstart', function(event) {
    // 存储要传递的数据
    event.dataTransfer.setData('text/plain', 'Dropped data');
    // 设置拖动的可视反馈图像
    const dragImage = document.createElement('img');
    dragImage.src = 'drag-image.png';
    event.dataTransfer.setDragImage(dragImage, -10, -10);
});
 
// 设置放置目标的事件监听器
const dropTarget = document.getElementById('dropTarget');
dropTarget.addEventListener('dragover', function(event) {
    // 阻止默认行为以允许放置
    event.preventDefault();
    // 设置光标样式
    event.dataTransfer.dropEffect = 'move';
});
 
dropTarget.addEventListener('drop', function(event) {
    // 阻止默认的打开链接或者输入行为
    event.preventDefault();
    // 获取拖动的数据
    const data = event.dataTransfer.getData('text/plain');
    // 执行放置操作
    console.log('Dropped: ', data);
});

在这个例子中,我们创建了一个拖动开始事件监听器,它在用户开始拖动元素时被触发。它设置了要传递的数据,并指定了一个图像作为拖动的可视反馈。同时,我们还创建了一个放置目标,它允许用户将数据放置在该元素上,并在放置操作时触发事件。在放置事件中,我们获取了拖动的数据并执行了相关的操作。

《JS实现拖曳排序效果并输出新的排序结果》源码在这里

好了,话题有点大,说的有点多。希望对您有所帮助,嘿嘿,喜欢我的分享,别忘了收藏+点赞。当然,若能评论就更完美了~