Drag&Drop API:实现拖拽操作
Drag&Drop API 是 Web 开发中一个非常有用的功能,它可以让我们实现拖拽操作。本文将介绍如何使用 Drag&Drop API 实现拖拽操作,包括设置元素为可拖拽、定义拖拽事件、设置拖拽效果等。
设置元素为可拖拽
要实现拖拽操作,首先需要将元素设置为可拖拽。我们可以使用 draggable
属性来设置元素是否可拖拽。当 draggable
属性设置为 true
时,元素就可以被拖拽了。例如:
<div draggable="true">可以拖拽的元素</div>
需要注意的是,当元素被设置为可拖拽时,它的默认行为会被禁止,即不再可以选中或复制元素内容。
定义拖拽事件
在设置元素为可拖拽后,我们需要定义拖拽事件来控制拖拽操作。Drag&Drop API 提供了一些事件来处理拖拽操作,包括 dragstart
、dragenter
、dragover
、dragleave
和 drop
等事件。
dragstart
:当拖拽操作开始时触发。在这个事件处理程序中,我们可以设置拖拽效果,例如设置被拖拽元素的样式或元素的数据。dragenter
:当拖拽元素进入可拖拽区域时触发。dragover
:当拖拽元素在可拖拽区域中移动时不断触发,可以在这个事件处理程序中设置拖拽效果。dragleave
:当拖拽元素离开可拖拽区域时触发。drop
:当拖拽元素放置在可拖拽区域时触发。在这个事件处理程序中,我们可以处理放置操作,例如将被拖拽元素移动到放置位置。
下面是一个示例,展示如何定义拖拽事件:
const dragElement = document.getElementById('drag');
const dropElement = document.getElementById('drop');
dragElement.addEventListener('dragstart', function(event) {
event.dataTransfer.setData('text/plain', '被拖拽的元素');
event.target.style.opacity = '0.5';
});
dropElement.addEventListener('dragenter', function(event) {
event.preventDefault();
event.target.style.backgroundColor = 'lightgray';
});
dropElement.addEventListener('dragover', function(event) {
event.preventDefault();
});
dropElement.addEventListener('dragleave', function(event) {
event.target.style.backgroundColor = '';
});
dropElement.addEventListener('drop', function(event) {
event.preventDefault();
const data = event.dataTransfer.getData('text/plain');
event.target.innerText = data;
event.target.style.backgroundColor = '';
dragElement.style.opacity= '1';
});
在这个示例中,我们首先获取了一个被拖拽元素和一个可放置元素,并分别为它们注册了相应的拖拽事件。在 dragstart
事件处理程序中,我们使用 event.dataTransfer.setData()
方法设置了被拖拽元素的数据类型和数据,这些数据可以在 drop
事件处理程序中使用。同时,我们也设置了被拖拽元素的透明度为 0.5,以表示它正在被拖拽。
在 dragenter
事件处理程序中,我们使用 event.preventDefault()
方法阻止了默认行为,并设置了可放置元素的背景色为灰色,表示它可以接受被拖拽元素。
在 dragover
事件处理程序中,我们同样使用 event.preventDefault()
方法阻止了默认行为,以便在 drop
事件处理程序中能够处理放置操作。
在 dragleave
事件处理程序中,我们将可放置元素的背景色恢复为默认值,表示它不再可以接受被拖拽元素。
在 drop
事件处理程序中,我们同样使用 event.preventDefault()
方法阻止了默认行为,并使用 event.dataTransfer.getData()
方法获取了被拖拽元素的数据。然后,我们将被拖拽元素的数据放置到可放置元素中,并将可放置元素的背景色恢复为默认值。最后,我们也将被拖拽元素的透明度恢复为 1。
设置拖拽效果
在 dragstart
事件处理程序中,我们可以设置拖拽效果。Drag&Drop API 提供了一些方法和属性,可以帮助我们设置拖拽效果。
event.dataTransfer.effectAllowed
:设置被拖拽元素的可允许放置效果。可选值包括none
、copy
、move
和link
。默认值为move
。event.dataTransfer.dropEffect
:设置拖拽元素的当前放置效果。可选值包括none
、copy
、move
和link
。默认值为none
。event.dataTransfer.setDragImage()
:设置拖拽元素的自定义图片,使其在拖拽过程中显示。这个方法需要传入一个图片元素和一个坐标偏移量作为参数,例如:
const dragElement = document.getElementById('drag');
const dragImage = new Image();
dragImage.src = 'drag-image.png';
dragElement.addEventListener('dragstart', function(event) {
event.dataTransfer.setData('text/plain', '被拖拽的元素');
event.dataTransfer.effectAllowed = 'move';
event.dataTransfer.setDragImage(dragImage, 0, 0);
});
在这个示例中,我们首先创建了一个图片元素,并将其赋值给 dragImage
变量。然后,在 dragstart
事件处理程序中,我们使用 event.dataTransfer.effectAllowed
属性设置了被拖拽元素的可允许放置效果为 move
,表示它可以被移动到放置位置。同时,我们也使用 event.dataTransfer.setDragImage()
方法设置了被拖拽元素的自定义图像为 dragImage
,这个图像将在拖拽过程中显示,偏移量为 (0, 0)。
拖拽文件
除了可以拖拽元素外,Drag&Drop API 还可以用来拖拽文件。当拖拽文件时,被拖拽元素的数据类型为 Files
,可以使用 event.dataTransfer.files
属性来获取拖拽的文件列表。下面是一个示例,展示如何拖拽文件:
<div id="drop-area">拖拽文件到这里</div>
const dropArea = document.getElementById('drop-area');
dropArea.addEventListener('dragover', function(event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
dropArea.style.backgroundColor = 'lightgray';
});
dropArea.addEventListener('dragleave', function(event) {
dropArea.style.backgroundColor = '';
});
dropArea.addEventListener('drop', function(event) {
event.preventDefault();
const fileList = event.dataTransfer.files;
for (const file of fileList) {
console.log(`拖拽了文件:${file.name}`);
}
dropArea.style.backgroundColor = '';
});
在这个示例中,我们首先获取了一个可放置元素,并为它注册了 dragover
、dragleave
和 drop
事件处理程序。在 dragover
事件处理程序中,我们使用 event.preventDefault()
方法阻止了默认行为,并设置了拖拽元素的放置效果为 copy
,表示它可以被复制到放置位置。同时,我们也将可放置元素的背景色设置为灰色,表示它可以接受被拖拽文件。
在 dragleave
事件处理程序中,我们将可放置元素的背景色恢复为默认值,表示它不再可以接受被拖拽文件。
在 drop
事件处理程序中,我们同样使用 event.preventDefault()
方法阻止了默认行为,并使用 event.dataTransfer.files
属性获取了拖拽的文件列表。然后,我们可以使用 for-of
循环遍历文件列表,并打印每个文件的名称。最后,我们也将可放置元素的背景色恢复为默认值。
实现拖拽排序
Drag&Drop API 还可以用来实现拖拽排序功能,例如拖拽列表项进行排序。下面是一个示例,展示如何使用 Drag&Drop API 实现拖拽排序:
<ul id="sortable">
<li>列表项1</li>
<li>列表项2</li>
<li>列表项3</li>
<li>列表项4</li>
<li>列表项5</li>
</ul>
const sortableList = document.getElementById('sortable');
let dragItem = null;
sortableList.addEventListener('dragstart', function(event) {
dragItem = event.target;
event.dataTransfer.effectAllowed = 'move';
});
sortableList.addEventListener('dragover', function(event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
const targetItem = event.target;
if (targetItem.tagName === 'LI' && targetItem !== dragItem) {
const rect = targetItem.getBoundingClientRect();
const offset = rect.y + rect.height / 2 > event.clientY ? 'before' : 'after';
if (offset === 'before') {
sortableList.insertBefore(dragItem, targetItem);
} else {
sortableList.insertBefore(dragItem, targetItem.nextSibling);
}
}
});
sortableList.addEventListener('dragend', function(event) {
dragItem = null;
});
在这个示例中,我们首先获取了一个可排序的列表,并为它注册了 dragstart
、dragover
和 dragend
事件处理程序。在 dragstart
事件处理程序中,我们将被拖拽的列表项保存到 dragItem
变量中,并设置了它的可允许放置效果为 move
,表示它可以被移动到放置位置。
在 dragover
事件处理程序中,我们使用 event.preventDefault()
方法阻止了默认行为,并设置了拖拽元素的放置效果为 move
,表示它可以被移动到放置位置。然后,我们获取了拖拽元素的目标列表项,并判断它是否为列表项,并且不是被拖拽的列表项。如果满足条件,我们使用 getBoundingClientRect()
方法获取了目标列表项的位置信息,并计算出被拖拽列表项应该插入的位置。最后,我们使用 insertBefore()
方法将被拖拽列表项插入到目标列表项的位置。
在 dragend
事件处理程序中,我们将 dragItem
变量设置为 null
,表示拖拽操作结束。
总结
Drag&Drop API 是 Web 开发中非常有用的功能,它可以让我们实现拖拽操作,包括拖拽元素、拖拽文件、拖拽排序等。在使用 Drag&Drop API 实现拖拽操作时,我们需要设置元素为可拖拽,并定义拖拽事件来控制拖拽操作。同时,我们也可以使用 Drag&Drop API 提供的方法和属性来设置拖拽效果,例如设置被拖拽元素的可允许放置效果、设置拖拽元素的当前放置效果等。
一系列的课程让你成为高级前端工程师。课程覆盖工作中所有常用的知识点和背后的使用逻辑,示例全部都为工作项目简化而来,学完即可直接上手开发!
即使你已经是高级前端工程师,在课程里也可能会发现新的知识点和技巧,让你的工作更加轻松!
《React 完全指南》课程,包含 React、React Router 和 Redux 详细介绍,所有示例改编自真实工作代码。点击查看详情。
《Vue 3.x 全家桶完全指南与实战》课程,包括 Vue 3.x、TypeScript、Vue Router 4.x、Vuex 4.x 所有初级到高级的语法特性详解,让你完全胜任 Vue 前端开发的工作。点击查看详情。
《React即时通信UI实战》课程,利用 Storybook、Styled-components、React-Spring 打造属于自己的组件库。
《JavaScript 基础语法详解》本人所著图书,包含 JavaScript 全面的语法知识和新特性, 可在京东、当当、淘宝等各大电商购买