HTML 拖放 API

HTML 拖放接口使应用程序能够在浏览器中使用拖放功能。

用户可以使用鼠标选择可拖动元素,将这些元素拖到可放置元素上,然后通过释放鼠标按钮将其放下。在拖动操作期间,可拖动元素的半透明表示形式跟随指针。

您可以自定义哪些元素可以变成可拖动的,可拖动元素产生的反馈类型以及可放置元素。

此 HTML 拖放概述包括接口的描述、向应用程序添加拖放支持的基本步骤以及接口的互操作性摘要。

概念和用法

拖动事件

HTML 拖放使用DOM 事件模型和从鼠标事件继承的拖动事件。典型的拖动操作始于用户选择可拖动元素,当用户将元素拖到可放置元素上时继续,然后在用户释放拖动的元素时结束。

在拖动操作期间,会触发几种事件类型,并且某些事件可能会触发多次,例如dragdragover事件。

每个拖动事件类型都有一个关联的事件处理程序

事件 在...时触发
drag ...拖动项(元素或文本选择)被拖动。
dragend ...拖动操作结束(例如释放鼠标按钮或按 Esc 键;请参阅完成拖动)。
dragenter ...拖动项进入有效的放置目标。(请参阅指定放置目标)。
dragleave ...拖动项离开有效的放置目标。
dragover ...拖动项正在拖动到有效的放置目标上,每隔几百毫秒。
dragstart ...用户开始拖动项目。(请参阅开始拖动操作)。
drop ...项目被放置到有效的放置目标上。(请参阅执行放置)。

注意:从操作系统将文件拖动到浏览器中时,不会触发dragstartdragend事件。

基础知识

本节总结了向应用程序添加拖放功能的基本步骤。

识别可拖动对象

要使元素可拖动,需要添加draggable属性和dragstart事件处理程序,如下面的代码示例所示

html
<script>
  function dragstartHandler(ev) {
    // Add the target element's id to the data transfer object
    ev.dataTransfer.setData("text/plain", ev.target.id);
  }

  window.addEventListener("DOMContentLoaded", () => {
    // Get the element by id
    const element = document.getElementById("p1");
    // Add the ondragstart event listener
    element.addEventListener("dragstart", dragstartHandler);
  });
</script>

<p id="p1" draggable="true">This element is draggable.</p>

有关更多信息,请参阅

定义拖动的的数据

应用程序可以自由地在拖动操作中包含任意数量的数据项。每个数据项都是特定type的字符串——通常是 MIME 类型,例如text/html

每个DragEvent都有一个dataTransfer属性,该属性保存事件的数据。此属性(它是DataTransfer对象)还具有管理拖动数据的方法。setData()方法用于将项目添加到拖动数据中,如下例所示。

js
function dragstartHandler(ev) {
  // Add different types of drag data
  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,
  );
}
  • 有关拖放中使用的常见数据类型的列表(例如文本、HTML、链接和文件),请参阅推荐的拖动类型
  • 有关拖动数据的更多信息,请参阅拖动数据

定义拖动图像

默认情况下,浏览器会提供一个在拖动操作期间出现在指针旁边的图像。但是,应用程序可以使用setDragImage()方法定义自定义图像,如下例所示。

js
// Create an image and then use it for the drag image.
// NOTE: change "example.gif" to a real image URL or the image
// will not be created and the default drag image will be used.
let img = new Image();
img.src = "example.gif";
function dragstartHandler(ev) {
  ev.dataTransfer.setDragImage(img, 10, 10);
}

详细了解拖动反馈图像,请参阅

定义放置效果

dropEffect属性用于控制用户在拖放操作期间获得的反馈。它通常会影响浏览器在拖动时显示的光标。例如,当用户将鼠标悬停在放置目标上时,浏览器的光标可能会指示将发生的操作类型。

可以定义三种效果

  1. copy表示将拖动的数据从其当前位置复制到放置位置。
  2. move表示将拖动的数据从其当前位置移动到放置位置。
  3. link表示将在源位置和放置位置之间创建某种形式的关系或连接。

在拖动操作期间,可以修改拖动效果以指示在某些位置允许某些效果。

以下示例显示了如何使用此属性。

js
function dragstartHandler(ev) {
  ev.dataTransfer.dropEffect = "copy";
}

有关更多详细信息,请参阅

定义放置区域

默认情况下,浏览器会阻止将任何内容放置到大多数 HTML 元素上时发生任何事情。要更改此行为,使元素成为放置区域可放置,该元素必须同时侦听dragoverdrop事件。

以下示例显示了如何使用这些属性,并包含每个属性的基本事件处理程序。

html
<script>
  function dragoverHandler(ev) {
    ev.preventDefault();
    ev.dataTransfer.dropEffect = "move";
  }
  function dropHandler(ev) {
    ev.preventDefault();
    // Get the id of the target and add the moved element to the target's DOM
    const data = ev.dataTransfer.getData("text/plain");
    ev.target.appendChild(document.getElementById(data));
  }
</script>

<p id="target" ondrop="dropHandler(event)" ondragover="dragoverHandler(event)">
  Drop Zone
</p>

请注意,每个处理程序都会调用preventDefault()以防止对此事件进行其他事件处理(例如触摸事件指针事件)。

有关更多信息,请参阅

处理放置效果

drop事件的处理程序可以以应用程序特定的方式处理拖动数据。

通常,应用程序使用getData()方法检索拖动项目,然后相应地处理它们。此外,应用程序语义可能因dropEffect的值和/或修饰键的状态而异。

以下示例显示了一个放置处理程序从拖动数据中获取源元素的id,然后使用id将源元素移动到放置元素

html
<script>
  function dragstartHandler(ev) {
    // Add the target element's id to the data transfer object
    ev.dataTransfer.setData("application/my-app", ev.target.id);
    ev.dataTransfer.effectAllowed = "move";
  }
  function dragoverHandler(ev) {
    ev.preventDefault();
    ev.dataTransfer.dropEffect = "move";
  }
  function dropHandler(ev) {
    ev.preventDefault();
    // Get the id of the target and add the moved element to the target's DOM
    const data = ev.dataTransfer.getData("application/my-app");
    ev.target.appendChild(document.getElementById(data));
  }
</script>

<p id="p1" draggable="true" ondragstart="dragstartHandler(event)">
  This element is draggable.
</p>
<div
  id="target"
  ondrop="dropHandler(event)"
  ondragover="dragoverHandler(event)">
  Drop Zone
</div>

有关更多信息,请参阅

拖动结束

在拖动操作结束时,dragend事件将在元素(即拖动开始的目标元素)上触发。

无论拖动是否完成或被取消,此事件都会触发。dragend事件处理程序可以检查dropEffect属性的值以确定拖动操作是否成功。

有关处理拖动操作结束的更多信息,请参阅

接口

HTML 拖放接口是DragEventDataTransferDataTransferItemDataTransferItemList

DragEvent接口有一个构造函数和一个dataTransfer属性,该属性是DataTransfer对象。

DataTransfer对象包含拖动事件的状态,例如正在执行的拖动类型(如copymove)、拖动的数据(一个或多个项目)以及每个拖动项目的 MIME 类型。DataTransfer对象还具有将项目添加到或从拖动数据中删除的方法。

DragEventDataTransfer接口应该是向应用程序添加 HTML 拖放功能所需的唯一接口。

每个 DataTransfer 对象都包含一个 items 属性,该属性是一个 list,其中包含 DataTransferItem 对象。一个 DataTransferItem 对象代表一个单独的拖动项,每个拖动项都有一个 kind 属性(stringfile)和一个 type 属性,用于表示数据项的 MIME 类型。 DataTransferItem 对象还提供方法来获取拖动项的数据。

DataTransferItemList 对象是一个 DataTransferItem 对象列表。列表对象提供方法用于将拖动项添加到列表中,从列表中删除拖动项,以及清除列表中的所有拖动项。

DataTransferDataTransferItem 接口之间的关键区别在于,前者使用同步的 getData() 方法来访问拖动项的数据,而后者则使用异步的 getAsString() 方法。

注意:DragEventDataTransfer 在桌面浏览器上得到广泛支持。但是,DataTransferItemDataTransferItemList 接口的浏览器支持有限。有关拖放互操作性的更多信息,请参阅 互操作性

示例

规范

规范
HTML 标准

另请参阅