巩固一下网页拖放事件

木头的喵喵拖孩

最近在做我的【学习&复习网站第二版】,在开发一个树形结构组件时遇到了个问题,之前一直都不重视,就是拖放的实现。
如下所示是目前已经实现好的拖放功能

之前也有做过拖拽的组件 记录一个公司项目(uniapp 原生实现异形范围选择器 slider) ,这里和它一起做一个总结。

准确来说, 记录一个公司项目(uniapp 原生实现异形范围选择器 slider) 仅用到了移动端特有的触摸事件,即:

  • touchstart
  • touchmove
  • touchend

以上这些 touch 系列事件能够实现了移动端网页的滑动拖拽条,
但我们现在要说的是不管移动端还是PC 端都可以使用的(主要是PC 端)拖放事件,即 drag 和 drop 系列事件

drag 和 drop

先介绍一下今天要介绍的主角:drag 和 drop 系列事件。
在英语中:drag 就是拖拽的意思,而 drop 就是降落(放下)的意思。

  • _drag_: 绑定在被拖拽的元素上,被拖拽元素移动时触发。
  • _dragStart_: 绑定在被拖拽的元素上,元素开始被拖拽时触发。
  • _dragEnd_: 绑定在被拖拽的元素上,元素结束被拖拽时触发。
  • _dragEnter_: 绑定在被放入的元素上,被拖拽元素进入被放入元素时触发。
  • _dragLeave_: 绑定在被放入的元素上,被拖拽元素离开被放入元素时触发。
  • _dragOver_: 绑定在被放入的元素上,被拖拽元素在被放入元素上移动时触发。
  • _drop_: 绑定在被放入的元素上,被拖拽元素在被放入元素上放下时触发。

首先要说明一点,要实现拖放功能,那么就需要两个元素参与进来,一个是被拖拽的元素,另一个是被放入的元素
以上事件有一部分是需要绑定在被拖拽的元素上的,而另一部分需要绑定在被放入的元素上,以此完成一个闭环。

还要注意,被拖拽的元素需要声明“draggable=”true””,否则是拖不动的。

代码参考

这里仅实现一个简单的拖拽和放下的例子,不涉及到树结构。
如对树结构有兴趣,可以参考 VUE 递归组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>drag and drop</title>

<style>
#content1,
#content2 {
height: 200px;
padding: 1em;
}

#content1 {
background-color: rgba(255, 0, 255, 0.2);
}

#content2 {
background-color: rgba(0, 255, 255, 0.2);
}

#drag-item {
display: inline-block;
padding: 1em;
background-color: greenyellow;
cursor: move;
}

#console {
width: 100%;
height: 300px;
resize: none;
}
</style>
</head>

<body>
<h3>拖动绿色元素到容器1或容器2</h3>

<!-- 容器1(被放入的元素) -->
<div id="content1">
<h3>容器1(粉色背景)</h3>
<!-- 被拖拽的元素,需要声明:draggable="true" -->
<div id="drag-item" draggable="true">请拖动我</div>
</div>

<!-- 容器2(被放入的元素) -->
<div id="content2">
<h3>容器2(蓝色背景)</h3>
</div>

<!-- 信息展示区 -->
<h3>信息输出</h3>
<textarea id="console"></textarea>

<script>
const $content1 = document.getElementById("content1"),
$content2 = document.getElementById("content2"),
$dragItem = document.getElementById("drag-item"),
$console = document.getElementById("console");

const consoleScrollToButton = () => {
$console.scrollTop = $console.scrollHeight;
};

// 这里为“被拖拽的元素”绑定事件
let dragTimer = 0,
dragInterval = 500;
const drag = (ev) => {
// 拖动时每100ms产生一个事件,频率太高,所以做一个节流
if (dragTimer) return;
dragTimer = setTimeout(() => {
let { offsetX, offsetY } = ev;
$console.value += `drag 元素正在被拖动,位置:x=${offsetX},y=${offsetY}\r\n`;
consoleScrollToButton();
dragTimer = 0;
}, dragInterval);
};
const dragstart = (ev) => {
$console.value += "dragstart 元素开始拖动了\r\n";
consoleScrollToButton();
};
const dragend = (ev) => {
$console.value += "dragstart 元素结束拖动了\r\n";
consoleScrollToButton();
};
$dragItem.addEventListener("drag", drag);
$dragItem.addEventListener("dragstart", dragstart);
$dragItem.addEventListener("dragend", dragend);

// 这里为“被放入的元素绑定事件”
const dragenter = (ev) => {
let name = ev.currentTarget.querySelector("h3").innerText;
$console.value += `dragenter 进入了${name}\r\n`;
consoleScrollToButton();
};
const dragleave = (ev) => {
let name = ev.currentTarget.querySelector("h3").innerText;
$console.value += `dragleave 离开了${name}\r\n`;
consoleScrollToButton();
};
let dragoverTimer = 0,
dragoverInterval = 500;
const dragover = (ev) => {
ev.preventDefault();
let { currentTarget } = ev;
// 拖动时每100ms产生一个事件,频率太高,所以做一个节流
if (dragoverTimer) return;
dragoverTimer = setTimeout(() => {
let name = currentTarget.querySelector("h3").innerText;
let { offsetX, offsetY } = ev;
$console.value += `drag 元素正在${name}上被拖动,位置:x=${offsetX},y=${offsetY}\r\n`;
consoleScrollToButton();
dragoverTimer = 0;
}, dragoverInterval);
};
const drop = (ev) => {
let name = ev.currentTarget.querySelector("h3").innerText;
$console.value += `drop 放入了${name}\r\n`;
ev.currentTarget.appendChild($dragItem);
consoleScrollToButton();
};
$content1.addEventListener("dragenter", dragenter);
$content2.addEventListener("dragenter", dragenter);
$content1.addEventListener("dragleave", dragleave);
$content2.addEventListener("dragleave", dragleave);
$content1.addEventListener("dragover", dragover);
$content2.addEventListener("dragover", dragover);
$content1.addEventListener("drop", drop);
$content2.addEventListener("drop", drop);
</script>
</body>
</html>

参考

HTML 拖放 API

  • 标题: 巩固一下网页拖放事件
  • 作者: 木头的喵喵拖孩
  • 创建于: 2024-06-01 16:39:56
  • 更新于: 2024-06-02 15:51:24
  • 链接: https://blog.xx-xx.top/2024/06/01/巩固一下网页拖放事件/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
此页目录
巩固一下网页拖放事件