如何使用 Vanilla JavaScript 和 HTML 创建拖放元素

介绍

拖放是一种常见的用户交互,您可以在许多图形用户界面中找到它。

已有 JavaScript 库可用于向您的应用程序添加拖放功能。但是,可能存在库不可用或引入项目不需要的开销或依赖项的情况。在这些情况下,了解现代 Web 浏览器中可用的 API 可以提供替代解决方案。

HTML拖放API依赖于DOM的事件模型我们就可以得到被拖动或下降,以更新拖动或丢弃元素信息。使用 JavaScript 事件处理程序,您可以将任何元素变成可拖动的项目或可以放入的项目。

在本教程中,我们将使用 HTML Drag and Drop API 和 vanilla JavaScript 构建一个拖放示例,以使用事件处理程序。

先决条件

要完成本教程,您需要:

  • 支持拖放 API(Chrome 4+、Firefox 3.5+、Safari 3.1+、Edge 18+)的现代 Web 浏览器。

步骤 1 — 创建项目和初始标记

我们的项目将包含一个容器,其中包含两种类型的子元素:

  • 可以拖动的子元素
  • 可以将元素放入其中的子元素

首先,打开终端窗口并创建一个新的项目目录:

  • mkdir drag-and-drop-example

接下来,导航到该目录:

  • cd drag-and-drop-example

然后,index.html在该目录中创建一个文件:

  • nano index.html

接下来,为 HTML 网页添加样板代码:

索引.html
<!DOCTYPE html>
<html>
  <head>
    <title>My Drag-and-Drop Example</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
  </body>
</html>

<body>标签之间添加您的draggable项目和您的dropzone(放置目标):

索引.html
<div class="example-parent">
  <div class="example-origin">
    <div
      id="draggable-1"
      class="example-draggable"
    >
      draggable
    </div>
  </div>

  <div
    class="example-dropzone"
  >
    dropzone
  </div>
</div>

保存并关闭文件。然后,创建一个style.css文件:

  • nano style.css

接下来,为我们index.html文件中的元素添加样式

样式文件
.example-parent {
  border: 2px solid #DFA612;
  color: black;
  display: flex;
  font-family: sans-serif;
  font-weight: bold;
}

.example-origin {
  flex-basis: 100%;
  flex-grow: 1;
  padding: 10px;
}

.example-draggable {
  background-color: #4AAE9B;
  font-weight: normal;
  margin-bottom: 10px;
  margin-top: 10px;
  padding: 10px;
}

.example-dropzone {
  background-color: #6DB65B;
  flex-basis: 100%;
  flex-grow: 1;
  padding: 10px;
}

这将为应用程序添加一些格式。现在您可以index.html在浏览器中查看并观察这会产生 adraggable <div>和 a dropzone <div>

可拖动和放置区 div 的屏幕截图

接下来,我们将<div>通过添加draggable属性明确地使第一个可拖动

索引.html
<div class="example-parent">
  <div class="example-origin">
    <div
      id="draggable-1"
      class="example-draggable"
      draggable="true"
    >
      draggable
    </div>
  </div>

  <div
    class="example-dropzone"
  >
    dropzone
  </div>
</div>

保存并关闭文件。

最后,index.html再次在浏览器中查看如果我们点击draggable <div>并在屏幕上拖动它,应该有它移动的视觉指示。

draggable属性的默认值为auto这意味着元素是否可拖动将由浏览器的默认行为决定。通常,这意味着文本选择、图像和链接无需指定即可拖动draggable="true"

您现在有一个带有可拖动元素的 HTML 文件。我们将继续添加onevent处理程序。

第 2 步 – 使用 JavaScript 处理拖放事件

目前,如果我们在拖动可拖动元素时释放鼠标,则不会发生任何事情。要在 DOM 元素上触发拖放操作,我们需要使用拖放 API:

  • ondragstart:此事件处理程序将附加到我们的draggable元素并在dragstart事件发生时触发
  • ondragover:此事件处理程序将附加到我们的dropzone元素并在dragover事件发生时触发
  • ondrop:此事件处理程序也将附加到我们的dropzone元素并在drop事件发生时触发

注:共有八个事件处理程序总数:ondragondragendondragenterondragexitondragleaveondragoverondragstart,和ondrop对于我们的示例,我们不会要求所有这些。

首先,让script.js我们在我们的 中引用一个新文件index.html

索引.html
<body>
  ...
  <script src="script.js"></script>
</body>

接下来,创建一个新script.js文件:

  • nano script.js

DataTransfer对象将跟踪与当前发生的拖动相关的信息。要在拖放时更新我们的元素,我们需要直接访问该DataTransfer对象。为此,我们可以dataTransfer从 DOM 元素的DragEvent.

注意:DataTransfer对象在技术上可以跟踪同时拖动的多个元素的信息。对于我们的示例,我们将专注于拖动一个元素。

dataTransfer对象的setData方法可用于设置当前拖动元素的拖动状态信息。它需要两个参数:

  • 声明第二个参数格式的字符串
  • 正在传输的实际数据

我们的目标是将我们的draggable元素移动到一个新的父元素。我们需要能够选择draggable具有唯一性元素id我们可以使用 方法设置id拖动元素的 ,setData以便稍后使用。

让我们重新访问我们的script.js文件并创建一个新函数来使用setData

脚本.js
function onDragStart(event) {
  event
    .dataTransfer
    .setData('text/plain', event.target.id);
}

注意:据报道,Internet Explorer 9 到 11 在使用'text/plain'. 'text'浏览器需要该格式

要更新拖动项的 CSS 样式,我们可以再次使用 DOM 事件访问其样式,并为currentTarget.

让我们添加到我们的函数并将其更改backgroundColoryellow

脚本.js
function onDragStart(event) {
  event
    .dataTransfer
    .setData('text/plain', event.target.id);

  event
    .currentTarget
    .style
    .backgroundColor = 'yellow';
}

注意:如果您想要仅拖动样式,您更改的任何样式都需要在放置时再次手动更新。如果您在开始拖动时更改任何内容,则被拖动的元素将保持新样式,除非您将其更改回来。

现在,我们有了用于拖动开始时的 JavaScript 函数。

我们可以添加ondragstartdraggable元素中index.html

索引.html
<div class="example-parent">
  <div class="example-origin">
    <div
      id="draggable-1"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      draggable
    </div>
  </div>

  <div class="example-dropzone">
    dropzone
  </div>
</div>

index.html在浏览器中查看如果您现在尝试拖动您的项目,将应用我们函数中声明的样式:

动画 gif 描绘了一个元素被拖动但不下降

但是,当您释放您的点击时,什么也不会发生。

按此顺序触发的下一个事件处理程序是ondragover

<div>浏览器中某些 DOM 元素(如s)的默认放置行为通常不接受放置。此行为将拦截我们试图实现的行为。为确保我们获得所需的丢弃行为,我们将应用preventDefault.

让我们重新访问该script.js文件并创建一个新函数以使用preventDefault. 将此代码添加到文件末尾:

脚本.js
function onDragOver(event) {
  event.preventDefault();
}

现在,我们可以添加ondragover到我们的dropzone元素中index.html

索引.html
<div class="example-parent">
  <div class="example-origin">
    <div
      id="draggable-1"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      draggable
    </div>
  </div>

  <div
    class="example-dropzone"
    ondragover="onDragOver(event);"
  >
    dropzone
  </div>
</div>

在这一点上,我们还没有写出处理实际掉落的代码。在此序列中触发的最终事件处理程序是ondrop

让我们重新访问我们的script.js文件并创建一个新函数。

我们可以使用dataTransferobject 的setData方法引用我们之前保存的数据我们将使用dataTransfer对象的getData方法。我们设置的数据是id,所以这就是返回给我们的:

脚本.js
function onDrop(event) {
  const id = event
    .dataTransfer
    .getData('text');
}

选择我们检索到的draggable元素id

脚本.js
function onDrop(event) {
  // ...

  const draggableElement = document.getElementById(id);
}

选择我们的dropzone元素:

脚本.js
function onDrop(event) {
  // ...

  const dropzone = event.target;
}

将我们的draggable元素附加dropzone

脚本.js
function onDrop(event) {
  // ...

  dropzone.appendChild(draggableElement);
}

重置我们的dataTransfer对象:

脚本.js
function onDrop(event) {
  // ...

  event
    .dataTransfer
    .clearData();
}

现在,我们可以添加ondrop到我们的dropzone元素中index.html

索引.html
<div class="example-parent">
  <div class="example-origin">
    <div
      id="draggable-1"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      draggable
    </div>
  </div>

  <div
    class="example-dropzone"
    ondragover="onDragOver(event);"
    ondrop="onDrop(event);"
  >
    dropzone
  </div>
</div>

一旦完成,我们就有了一个完整的拖放功能。index.html在浏览器中查看并将draggable元素拖动dropzone.

动画 gif 描绘了一个元素被拖放到放置目标中

我们的示例处理单个可拖动项目和单个放置目标的场景。您可以拥有多个可拖动项目、多个放置目标,并使用所有其他拖放 API 事件处理程序对其进行自定义。

第 3 步 – 使用多个可拖动项目构建高级示例

下面是如何使用此 API 的另一个示例:带有可拖动任务的待办事项列表,您可以将其从一"To-do"移动到另一"Done"列。

动画 gif 描绘了多个待办事项被拖放到“完成”列中

要创建您自己的待办事项列表,请添加更多具有唯一ids 的可拖动元素index.html

索引.html
<div class="example-parent">
  <h1>To-do list</h1>
  <div class="example-origin">
    To-do
    <div
      id="draggable-1"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      thing 1
    </div>
    <div
      id="draggable-2"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      thing 2
    </div>
    <div
      id="draggable-3"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      thing 3
    </div>
    <div
      id="draggable-4"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      thing 4
    </div>
  </div>

  <div
    class="example-dropzone"
    ondragover="onDragOver(event);"
    ondrop="onDrop(event);"
  >
    Done
  </div>
</div>

index.html在浏览器中查看并将待办事项列中的项目拖到完成列。您已经创建了一个待办事项应用程序并测试了该功能。

结论

在本文中,您创建了一个待办事项应用程序来探索适用于现代 Web 浏览器的拖放功能。

拖放 API 提供了多种选项,用于自定义除拖放之外的操作。例如,您可以更新拖动项目的 CSS 样式。此外,您可以选择复制可拖动项目,以便在放置时复制它,而不是移动项目。

请记住,虽然许多 Web 浏览器支持此技术,但如果您的受众包含不支持此功能设备,您可能无法依赖它

要了解有关使用拖放 API 可以放置的所有内容的更多信息,请查看MDN 的相关文档

觉得文章有用?

点个广告表达一下你的爱意吧 !😁