如何使用 HTML 拖放 API

探索 HTML 拖放 API 的强大功能

拖放功能对于提升用户互动和打造流畅的用户体验至关重要。不论是构建文件上传器、可排序列表,还是互动游戏,掌握如何运用此 API 的能力都是 Web 开发工具包中的一项关键技能。

HTML 拖放的基础知识

在典型的拖放系统中,存在两种类型的元素:第一种是用户可以使用鼠标移动的“可拖动”元素;第二种是通常用于指示用户放置元素位置的“可放置”元素。

要实现拖放,必须告知浏览器哪些元素是可拖动的。 为了使元素可拖动,需要将其 HTML 属性 draggable 设置为 true,如下所示:

 <div draggable="true">这个元素可以拖动</div>

当用户开始触发拖动事件时,浏览器会提供默认的“幽灵”图像,通常用于反馈当前正在拖动的元素。

您可以自定义此图像,提供自己的图像。 为此,请从 DOM 中选择可拖动元素,创建一个新图像来表示自定义反馈图像,然后添加一个 dragstart 拖动事件监听器,如下所示:

 let img = new Image();
img.src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Twemoji_1f600.svg/220px-Twemoji_1f600.svg.png";

document.querySelector('div').addEventListener('dragstart', (event)=>{
    event.dataTransfer.setDragImage(img, 10, 10);
})

在上面的代码块中,setDragImage 方法接收三个参数。第一个参数引用图像。其余参数分别表示图像的水平和垂直偏移量。当您在浏览器中运行代码并开始拖动元素时,自定义的拖动图像将替换默认的图像。

如果希望允许元素放置,必须通过取消 dragenterdragover 事件的默认行为来实现,如下所示:

 const dropElement = document.querySelector("drop-target");

dropElement.addEventListener("dragenter", (ev) => {
  ev.preventDefault();
});

dropElement.addEventListener("dragover", (ev) => {
  ev.preventDefault();
});

理解 DragEvent 接口

JavaScript 提供了 DragEvent 接口,它代表用户的拖放交互。以下是 DragEvent 接口可能触发的事件类型列表。

  • drag: 当用户正在拖动元素时触发。
  • dragend: 当拖动操作结束或被用户中断时触发。典型的拖动操作可以通过释放鼠标按钮或按下 Esc 键来结束。
  • dragenter: 当被拖动的元素进入一个有效的放置目标时触发。
  • dragleave: 当被拖动的元素离开放置目标时触发。
  • dragover: 当用户将可拖动元素拖动到放置目标上方时触发。
  • dragstart: 在拖动操作开始时触发。
  • drop: 当用户将元素放置到放置目标上时触发。

当从浏览器外部的环境(例如操作系统文件管理器)将文件拖入浏览器时,浏览器不会触发 dragstartdragend 事件。

如果您想以编程方式调度自定义拖动事件,DragEvent 非常有用。例如,如果您希望一个 div 在页面加载时触发自定义拖动事件,请执行以下操作。首先,创建一个新的自定义 DragEvent(),如下所示:

 const customDragStartEvent = new DragEvent('dragstart', {
    dataTransfer: new DataTransfer(),
})

const customDragEndEvent = new DragEvent('dragend');

在上面的代码块中,customDragStartEvent 表示 DragEvent() 的一个实例。在 customDragStartEvent 中,存在两个构造函数参数。第一个表示拖动事件的类型,它可以是前面提到的七种事件类型之一。

第二个参数是一个带有 dataTransfer 键的对象,它代表 DataTransfer 的实例,您将在本指南的后面部分了解更多信息。接下来,从文档对象模型 (DOM) 中获取要触发事件的元素。

 const draggableElement = document.querySelector("#draggable");

然后添加事件监听器,如下所示:

   draggableElement.addEventListener('dragstart', (event) => {
    console.log('拖动开始!');
    event.dataTransfer.setData('text/plain', '你好,世界!');
  });

  draggableElement.addEventListener('dragend', () => {
    console.log('拖动结束!');
  });

在上面的第一个事件监听器中,回调函数会记录文本“拖动开始!”并调用事件对象的 dataTransfer 属性上的 setData 方法。现在,您可以像这样触发自定义事件:

 draggableElement.dispatchEvent(customDragStartEvent);
draggableElement.dispatchEvent(customDragEndEvent);

使用 dataTransfer 传输数据

dataTransfer 对象在拖放操作期间充当源元素(可拖动项)和目标元素(可放置区域)之间的桥梁。它充当您希望在这些元素之间共享的数据的临时存储容器。

数据可以采用多种形式,如文本、URL 或自定义数据类型,使其成为实现各种拖放功能的多功能工具。

使用 setData() 打包数据

要将数据从可拖动元素传输到可放置元素,可以使用 dataTransfer 对象提供的 setData() 方法。此方法允许您打包要传输的数据并指定数据类型。这是一个基本示例:

 element.addEventListener('dragstart', (event) => {
  event.dataTransfer.setData('text/plain', '你好,世界!');
});

当用户开始拖动指定元素时,setData() 会将文本“你好,世界!”打包为数据类型 text/plain。该数据现在与拖动事件关联,并且可以在放置操作期间由可放置目标访问。

使用 getData() 检索数据

在接收端,在可放置元素的事件监听器中,您可以使用 getData() 方法检索传输的数据:

 element.addEventListener('drop', (event) => {
  const transferredData = event.dataTransfer.getData('text/plain');
  console.log(`接收到的数据: ${transferredData}`);
});

上面的代码块检索与之前使用 setData() 方法设置的数据类型(text/plain)相同的数据。 这允许您根据需要在可放置元素的上下文中访问和操作传输的数据。

拖放界面的用例

将拖放功能集成到您的 Web 应用程序中可以带来强大的增强功能,但了解何时以及为何应该实现它至关重要。

  • 文件上传器:允许用户将文件直接从桌面或文件管理器拖动到指定的放置区域,简化上传过程。
  • 可排序列表:如果您的应用程序涉及项目列表,例如任务列表、播放列表或图像库,用户可能会喜欢通过拖放对项目重新排序的功能。
  • 交互式仪表板:对于数据可视化和报告工具,拖放可以成为用户通过重新排列小部件和图表来自定义仪表板的强大方法。

牢记可访问性

虽然拖放可以在视觉上吸引人并增强用户体验,但确保所有用户(包括残障人士)都能访问您的实现至关重要。提供替代的交互方式,如键盘控制,以确保您的应用程序具有包容性。