介绍
拖放是常见的用户交互,您可以在许多图形用户界面中找到。
但是,有些情况下,库可能无法使用,或者引入了项目不需要的过剩或依赖性,在这些情况下,对现代Web浏览器中可用的API的知识可以提供替代解决方案。
HTML Drag and Drop API依靠DOM的事件模型来获取被拖拉或放下的东西的信息,并在拖拉或放下时更新该元素。
在本教程中,我们将使用Vanilla JavaScript的HTML Drag and Drop API构建一个拖放示例,以使用事件处理器。
前提条件
要完成本教程,您将需要:
- 支持 Drag and Drop API 的现代网页浏览器(Chrome 4+, Firefox 3.5+, Safari 3.1+, Edge 18+)。
步骤 1 – 创建项目和初始标记
我们的项目将包括两个类型的儿童元素的容器:
- 孩子元素,你可以拖
- 孩子元素,可能有元素落入它们
首先,打开终端窗口并创建一个新的项目目录:
1mkdir drag-and-drop-example
接下来,导航到该目录:
1cd drag-and-drop-example
然后,在该目录中创建一个index.html
文件:
1nano index.html
接下来,为 HTML 网页添加 boilerplate 代码:
1[label index.html]
2<!DOCTYPE html>
3<html>
4 <head>
5 <title>My Drag-and-Drop Example</title>
6 <link rel="stylesheet" href="style.css" />
7 </head>
8 <body>
9 </body>
10</html>
然后在<body>
标签之间添加你的draggable
项目和你的dropzone
(降落目标):
1[label index.html]
2<div class="example-parent">
3 <div class="example-origin">
4 <div
5 id="draggable-1"
6 class="example-draggable"
7 >
8 draggable
9 </div>
10 </div>
11
12 <div
13 class="example-dropzone"
14 >
15 dropzone
16 </div>
17</div>
保存并关闭文件,然后创建一个style.css
文件:
1nano style.css
接下来,在我们的 index.html 文件中添加元素的样式:
1[label style.css]
2.example-parent {
3 border: 2px solid #DFA612;
4 color: black;
5 display: flex;
6 font-family: sans-serif;
7 font-weight: bold;
8}
9
10.example-origin {
11 flex-basis: 100%;
12 flex-grow: 1;
13 padding: 10px;
14}
15
16.example-draggable {
17 background-color: #4AAE9B;
18 font-weight: normal;
19 margin-bottom: 10px;
20 margin-top: 10px;
21 padding: 10px;
22}
23
24.example-dropzone {
25 background-color: #6DB65B;
26 flex-basis: 100%;
27 flex-grow: 1;
28 padding: 10px;
29}
现在你可以在浏览器中查看index.html
,并注意到这会产生一个draggable``<div>
和一个dropzone``<div>
。
接下来,我们将通过添加draggable
属性来明确地使第一个<div>
可拖动:
1[label index.html]
2<div class="example-parent">
3 <div class="example-origin">
4 <div
5 id="draggable-1"
6 class="example-draggable"
7 draggable="true"
8 >
9 draggable
10 </div>
11 </div>
12
13 <div
14 class="example-dropzone"
15 >
16 dropzone
17 </div>
18</div>
保存并关闭文件。
最后,在浏览器中再次查看index.html
。如果我们点击draggable``<div>
,然后把它拖过屏幕,应该有视觉指示它在移动。
draggable
属性的默认值为auto
。这意味着该元素是否可拖放,将由您的浏览器的默认行为决定。
您现在有一个具有可拖放元素的HTML文件,我们将继续添加onevent
处理器。
步骤 2 — 使用 JavaScript 处理拖放事件
目前,如果我们在拖动可拖动元素时释放鼠标,则不会发生任何事情. 要在 DOM 元素上触发拖动或下降的操作,我们需要使用 Drag and Drop API:
ondragstart
:此事件处理器将附加到我们的draggable
元素,并在发生dragstart
事件时点燃ondragover
:当发生dragover
事件时,此事件处理器将附加到我们的dropzone
元素和火力ondrop
:此事件处理器也将附加到我们的dropzone
元素和火力
<$>[注]
**注:**共有八个事件处理器:ondrag
,ondragend
,ondragenter
,ondragexit
,ondragleave
,ondragover
,ondragstart
和ondrop
。
首先,让我们在我们的index.html中引用一个新的script.js
文件:
1[label index.html]
2<body>
3 ...
4 <script src="script.js"></script>
5</body>
接下来,创建一个新的script.js
文件:
1nano script.js
DataTransfer
对象将跟踪与当前拖动发生有关的信息。要更新我们在拖动和拖动时的元素,我们需要直接访问DataTransfer
对象。
<$>[注]
注: DataTransfer
对象可以技术上跟踪同时拖拉的多个元素的信息。
dataTransfer
对象的setData
方法可用于为您当前拖动的元素设置拖动状态信息。
- 声明第二参数 的格式的字符串 * 正在传输的实际数据
我们的目标是将我们的draggable
元素移动到一个新的母元素. 我们需要能够选择我们的draggable
元素具有独特的id
。
让我们重新浏览我们的script.js
文件并创建一个新的函数来使用setData
:
1[label script.js]
2function onDragStart(event) {
3 event
4 .dataTransfer
5 .setData('text/plain', event.target.id);
6}
<$>[注]
**注:**据报道,Internet Explorer 9 至 11 使用文本/平面
有问题。
为了更新被拖拉的项目的 CSS 风格,我们可以使用 DOM 事件再次访问其风格,并为当前目标
设置我们想要的任何风格。
让我们添加到我们的函数并将背景颜色
更改为黄色
:
1[label script.js]
2function onDragStart(event) {
3 event
4 .dataTransfer
5 .setData('text/plain', event.target.id);
6
7 event
8 .currentTarget
9 .style
10 .backgroundColor = 'yellow';
11}
<$>[注] **注:**您更改的任何风格都需要在下落时手动更新,如果您想要只有拖动的风格。
现在,我们有我们的JavaScript功能,用于拖拉开始时。
我们可以在index.html中的draggable
元素中添加ondragstart
:
1[label index.html]
2<div class="example-parent">
3 <div class="example-origin">
4 <div
5 id="draggable-1"
6 class="example-draggable"
7 draggable="true"
8 ondragstart="onDragStart(event);"
9 >
10 draggable
11 </div>
12 </div>
13
14 <div class="example-dropzone">
15 dropzone
16 </div>
17</div>
查看您的浏览器中的index.html
。如果你现在试图拖动您的项目,我们的功能中声明的样式将被应用:
但是,当你释放你的点击时,不会发生任何事情。
在此序列中发射的下一个事件处理器是ondragover
。
浏览器中某些 DOM 元素的默认 drop 行为通常不接受 dropping. 这种行为会拦截我们正在试图实现的行为. 为了确保我们获得所需的 drop 行为,我们将应用preventDefault。
让我们重新浏览script.js
文件并创建一个新的函数以使用preventDefault
。
1[label script.js]
2function onDragOver(event) {
3 event.preventDefault();
4}
现在,我们可以在index.html中的dropzone
元素中添加ondragover
:
1[label index.html]
2<div class="example-parent">
3 <div class="example-origin">
4 <div
5 id="draggable-1"
6 class="example-draggable"
7 draggable="true"
8 ondragstart="onDragStart(event);"
9 >
10 draggable
11 </div>
12 </div>
13
14 <div
15 class="example-dropzone"
16 ondragover="onDragOver(event);"
17 >
18 dropzone
19 </div>
20</div>
在此时刻,我们还没有写代码来处理实际下降,在这个序列中发射的最后事件处理器是ondrop
。
让我们重新浏览我们的script.js
文件并创建一个新的函数。
我们可以用dataTransfer
对象的setData
方法参考我们之前保存的数据,我们会使用dataTransfer
对象的getData
方法,我们设置的数据是id
,所以这就是我们将返回的:
1[label script.js]
2function onDrop(event) {
3 const id = event
4 .dataTransfer
5 .getData('text');
6}
选择我们的draggable
元素与我们获取的id
:
1[label script.js]
2function onDrop(event) {
3 // ...
4
5 const draggableElement = document.getElementById(id);
6}
选择我们的dropzone
元素:
1[label script.js]
2function onDrop(event) {
3 // ...
4
5 const dropzone = event.target;
6}
将我们的draggable
元素附加到dropzone
:
1[label script.js]
2function onDrop(event) {
3 // ...
4
5 dropzone.appendChild(draggableElement);
6}
重置我们的数据传输
对象:
1[label script.js]
2function onDrop(event) {
3 // ...
4
5 event
6 .dataTransfer
7 .clearData();
8}
现在,我们可以在index.html中的dropzone
元素中添加ondrop
:
1[label index.html]
2<div class="example-parent">
3 <div class="example-origin">
4 <div
5 id="draggable-1"
6 class="example-draggable"
7 draggable="true"
8 ondragstart="onDragStart(event);"
9 >
10 draggable
11 </div>
12 </div>
13
14 <div
15 class="example-dropzone"
16 ondragover="onDragOver(event);"
17 ondrop="onDrop(event);"
18 >
19 dropzone
20 </div>
21</div>
一旦完成,我们有一个完成的拖放功能. 在您的浏览器中查看index.html
,然后将拖放
元素拖到dropzone
。
我们的示例处理了一个可拖放的项目和一个可拖放的目标的场景. 您可以拥有多个可拖放的项目,多个可拖放的目标,并与所有其他拖放 API 事件处理器进行定制。
步骤 3 – 用多个可拖动项目构建一个先进的示例
以下是您可以使用此 API 的另一个例子:一个可拖动任务列表,您可以将其从要做
列移动到完成
列。
若要创建自己的任务列表,请将具有独特的id
的更多可拖动元素添加到index.html
:
1[label index.html]
2<div class="example-parent">
3 <h1>To-do list</h1>
4 <div class="example-origin">
5 To-do
6 <div
7 id="draggable-1"
8 class="example-draggable"
9 draggable="true"
10 ondragstart="onDragStart(event);"
11 >
12 thing 1
13 </div>
14 <div
15 id="draggable-2"
16 class="example-draggable"
17 draggable="true"
18 ondragstart="onDragStart(event);"
19 >
20 thing 2
21 </div>
22 <div
23 id="draggable-3"
24 class="example-draggable"
25 draggable="true"
26 ondragstart="onDragStart(event);"
27 >
28 thing 3
29 </div>
30 <div
31 id="draggable-4"
32 class="example-draggable"
33 draggable="true"
34 ondragstart="onDragStart(event);"
35 >
36 thing 4
37 </div>
38 </div>
39
40 <div
41 class="example-dropzone"
42 ondragover="onDragOver(event);"
43 ondrop="onDrop(event);"
44 >
45 Done
46 </div>
47</div>
在浏览器中查看index.html
,然后将To-do
列中的项目拖到Done
列,您已经创建了一个To-do
应用程序并测试了其功能。
结论
在本文中,您创建了一个要做的应用程序来探索现代Web浏览器可用的拖放功能。
Drag and Drop API 提供了多种选项来自定义您的操作,而不是拖放。例如,您可以更新拖放的项目的 CSS 样式。
请记住,虽然许多网页浏览器支持此技术,但如果您的观众包括不支持此功能的设备(https://caniuse.com/#feat=dragndrop),则您可能无法依靠该技术。
要了解有关您可以放弃的 Drag and Drop API 的更多信息,请参阅它上的 MDN 的文档。