HTML Drag and Drop API - 使应用程序能够在浏览器中使用拖放功能
HTML 拖放接口使应用程序能够在浏览器中使用拖放功能。用户可以使用鼠标选择可拖动元素,将这些元素拖动到可放置元素,然后通过释放鼠标按钮来放置它们。在拖动操作过程中,可拖动元素会以半透明的表现形式会跟随指针移动。
对于网站、扩展和 XUL 应用程序,您可以自定义哪些元素可以变为可拖动元素、可拖动元素产生的反馈类型以及可放置元素。
此 HTML 拖放概述包括接口说明、向应用程序添加拖放支持的基本步骤以及接口的互操作性摘要。
拖动事件
HTML 拖放使用DOM 事件模型
和从鼠标事件
继承的拖动事件
。典型的拖动操作开始于用户选择可拖动元素,将元素拖动到可放置元素,然后释放被拖动元素。
在拖动操作期间,会触发多种事件类型,并且某些事件可能会触发多次,例如 drag
和 dragover
事件。
事件 | 事件处理程序 | 触发时机 |
---|---|---|
drag |
ondrag |
当拖动的项目(元素或选择的文本)被拖动。 |
dragend |
ondragend |
当拖动操作结束(例如释放鼠标按钮或按 Esc 键;请参阅完成拖动。) |
dragenter |
ondragenter |
当拖动的项目进入有效的放置目标。(请参阅指定放置目标。) |
dragexit |
ondragexit |
当元素不再是拖动操作的直接选择目标。 |
dragleave |
ondragleave |
当拖动的项目离开有效的放置目标时。 |
dragover |
ondragover |
当拖动的项目被拖动到有效的放置目标上时,每次隔几百毫秒。 |
dragstart |
ondragstart |
当用户开始拖动项目时。(请参阅开始拖动操作。) |
drop |
ondrop |
当一个项目被放置在一个有效的放置目标上时。(请参阅执行放置。) |
注意: 将文件从操作系统拖入浏览器时,不会触发 dragstart
和 dragend
事件。
接口
HTML 拖放接口包含了 DragEvent
、DataTransfer
、DataTransferItem
和 DataTransferItemList
.
DragEvent
接口有一个构造函数和一个 dataTransfer
属性,它是一个 DataTransfer
对象。
DataTransfer
对象包括拖动事件的状态,例如正在完成的拖动类型(如 copy
或 move
)、拖动的数据(一个或多个项目)和每个拖动项目的 MIME 类型。DataTransfer
对象还具有向拖动数据添加或删除项目的方法。
DragEvent
和 DataTransfer
接口应该是向应用程序添加 HTML 拖放功能所需的唯一接口。(Firefox 向 DataTransfer
对象添加了一些特定的扩展,注意这些扩展仅适用于 Firefox。)
每个 DataTransfer
对象都包含一个 items
属性,它是一个包含 DataTransferItem
对象的列表
。一个 DataTransferItem
对象代表一个拖动项目,每个对象都有一个 kind
属性(string
或 file
)和一个 type
属性表示数据项的 MIME 类型。DataTransferItem
对象也有获取拖动项数据的方法。
DataTransferItemList
对象是一个包含 DataTransferItem
对象的列表。该对象具有向列表添加拖动项、从列表中删除拖动项以及清除所有拖动项的列表的方法。
DataTransfer
和 DataTransferItem
接口之间的主要区别在于前者使用同步 getData()
方法来访问拖动项的数据,但后者使用异步 getAsString()
方法。
注意: DragEvent
和 DataTransfer
在桌面浏览器上得到广泛支持。但是,DataTransferItem
和 DataTransferItemList
接口的浏览器支持有限。有关拖放互操作性的更多信息,请参阅互操作性。
特定于 Gecko 的接口
Mozilla 和 Firefox 支持标准拖放模型中没有的一些功能。这些是帮助拖动多个项目或非字符串数据(如文件)的便利功能。有关详细信息,请参阅 拖放多个项目。此外,请参阅 DataTransfer
参考页面,了解所有 Gecko 特有属性 和 Gecko 特有方法。
基础知识
本节总结了向应用程序添加拖放功能的基本步骤。
确定什么是可拖动
使元素可拖动,需要添加 draggable
属性和 ondragstart
全局事件处理程序,如以下代码实例所示:
<script>
function dragstart_handler(ev) {
// 将目标元素的 id 添加到数据传输对象
ev.dataTransfer.setData("text/plain", ev.target.id);
}
window.addEventListener('DOMContentLoaded', () => {
// 通过 id 获取元素
const element = document.getElementById("p1");
// 添加 ondragstart 事件监听器
element.addEventListener("dragstart", dragstart_handler);
});
</script>
<p id="p1" draggable="true">该元素是可拖动的。</p>
有关更多信息,请参阅:
定义拖动的数据
该应用程序可以自由地在拖动操作中包含任意数量的数据项。每个数据项都是一个特定 type
的 string
—— 通常是一个 MIME 类型,例如 text/html
。
每个拖动事件
都有一个 dataTransfer
属性,用于保存事件的数据。这个属性(它是一个 DataTransfer
对象)也有管理拖动数据的方法。setData()
方法用于向拖动数据添加项目,如下例所示。
function dragstart_handler(ev) {
// 添加不同类型的拖拽数据
ev.dataTransfer.setData("text/plain", ev.target.innerText);
ev.dataTransfer.setData("text/html", ev.target.outerHTML);
ev.dataTransfer.setData("text/uri-list", ev.target.ownerDocument.location.href);
}
定义拖动的图像
默认情况下,浏览器提供在拖动操作期间出现在指针旁边的图像。但是,应用程序可以使用 setDragImage()
方法定义自定义图像,如下例所示。
function dragstart_handler(ev) {
// 创建一个图像,然后将其用于拖动图像。
// 注意: 将 "example.gif "改为真正的图像 URL,
// 否则将不会创建图像,而会使用默认的拖动图像。
let img = new Image();
img.src = 'example.gif';
ev.dataTransfer.setDragImage(img, 10, 10);
}
了解有关拖动反馈图像的更多信息:
定义拖动效果
dropEffect
属性用于控制在拖放操作期间向用户提供的反馈。它通常会影响浏览器在拖动时显示的光标。例如,当用户将鼠标悬停在放置目标上时,浏览器的光标可能会指示将发生的操作类型。
可以定义三种效果:
copy
表示将拖动的数据从其当前位置复制到放置位置。move
表示拖动的数据将从当前位置移动到放置位置。link
表示将在源位置和放置位置之间创建某种形式的关系或连接。
在拖动操作期间,可以修改拖动效果以指示在某些位置允许某些效果。
以下实例显示了如何使用此属性。
function dragstart_handler(ev) {
ev.dataTransfer.dropEffect = "copy";
}
有关更多详细信息,请参阅:
定义一个放置区域
默认情况下,当把内容放到大多数 HTML 元素上时,浏览器不会有任何的效果。要更改该行为以使元素成为放置区域或可放置,该元素必须同时具有 ondragover
和 ondrop
事件处理程序属性。
以下实例显示了如何使用这些属性,并包括每个属性的基本事件处理程序。
<script>
function dragover_handler(ev) {
ev.preventDefault();
ev.dataTransfer.dropEffect = "move";
}
function drop_handler(ev) {
ev.preventDefault();
// 获取目标的 id 并将移动的元素添加到目标的 DOM
const data = ev.dataTransfer.getData("text/plain");
ev.target.appendChild(document.getElementById(data));
}
</script>
<p id="target" ondrop="drop_handler(event)" ondragover="dragover_handler(event)">放置区域</p>
请注意,每个处理程序都会调用 preventDefault()
以防止对此事件(例如 触摸事件 或 指针事件)进行额外的事件处理。
有关更多信息,请参阅:
处理放置效果
drop
事件的处理程序可以以特定于应用程序的方式自由处理拖动数据。
通常,应用程序使用 getData()
方法来获取拖动项,然后相应地处理它们。此外,应用程序语义可能因 dropEffect
的值和 / 或修饰键的状态而异。
以下实例显示了一个放置处理程序,它从拖动数据中获取源元素的 id
,然后使用 id
将源元素移动到放置元素:
<script>
function dragstart_handler(ev) {
// 将目标元素的 id 添加到数据传输对象
ev.dataTransfer.setData("application/my-app", ev.target.id);
ev.dataTransfer.effectAllowed = "move";
}
function dragover_handler(ev) {
ev.preventDefault();
ev.dataTransfer.dropEffect = "move"
}
function drop_handler(ev) {
ev.preventDefault();
// 获取目标的 id 并将移动的元素添加到目标的 DOM
const data = ev.dataTransfer.getData("application/my-app");
ev.target.appendChild(document.getElementById(data));
}
</script>
<p id="p1" draggable="true" ondragstart="dragstart_handler(event)">此元素是可拖动的。</p>
<div id="target" ondrop="drop_handler(event)" ondragover="dragover_handler(event)">放置区域</div>
有关更多信息,请参阅:
拖动结束
在拖动操作结束时,在源元素(即拖动开始的目标元素)上会触发 dragend
事件。
无论拖动是完成还是取消,都会触发此事件。dragend
事件处理程序可以检查 dropEffect
属性的值来确定拖动操作是否成功。
有关处理拖动操作结束的更多信息,请参阅:
互操作性
在 DataTransferItem 接口的浏览器兼容性表 中可以看出,桌面浏览器之间的拖放互操作性比较广泛(除了 DataTransferItem
和 DataTransferItemList
接口支持较少)。该数据还表明移动浏览器之间的拖放支持非常低。
实例和演示
- 使用
DataTransfer
接口复制和移动元素 - 使用
DataTransferListItem
接口复制和移动元素 - 拖放文件(仅限 Firefox):https://jsfiddle.net/9C2EF/
- 拖放文件(所有浏览器): https://jsbin.com/hiqasek/
- 使用拖放 API 的停车项目:https://park.glitch.me/(你可以在这里编辑)
规范
规范 | 状态 | 备注 |
---|---|---|
HTML Living Standard | 现行的标准 | - |