HTML5中实现元素拖放竟然如此简单
1、元素拖放简介
在HTML5之前,如果想要实现一个元素的拖放效果,我们一般需要结合该元素的onmousedown、onmousemove、onmouseup等多个事件来共同完成。这种方式代码量非常大,而且也仅限于在浏览器内的元素间拖放,不能实现跨应用拖放。在HTML5中,我们只需要给元素添加一个draggable属性,然后设置该属性值为true,就能实现元素的拖放。拖放,指的是“拖拽”和“释放”。在页面中进行一次拖放操作,我们必须先弄清楚两个元素:“源元素”和“目标元素”。“源元素”指的是被拖拽的那个元素,“目标元素”指的是源元素最终被释放到的那个元素。HTML5的拖放事件总共有7个,分为两类“源元素”触发的事件和“目标元素”触发的事件,详见下表:
事件类型 | 事件 | 说明 |
---|---|---|
“源元素”触发 | ondragstart | 开始拖放 |
“源元素”触发 | ondrag | 拖放过程中 |
“源元素”触发 | ondragend | 结束拖放 |
“目标元素”触发 | ondragenter | 当被拖放的元素进入本元素时 |
“目标元素”触发 | ondragover | 当被拖放的元素正在本元素范围内移动时 |
“目标元素”触发 | ondragleave | 当被拖放的元素离开本元素时 |
“目标元素”触发 | ondrop | 当“源元素”释放到本元素时 |
一个完整的拖放事件过程如下图所示,我们可以轻松地使用上表所示的事件来处理复杂的拖放效果。
举例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
body {
position: relative;
}
img {
position: absolute;
width: 200px;
height: 200px;
}
</style>
<script>
window.onload = function () {
const oImg = document.getElementsByTagName("img")[0];
let offsetX, offsetY;
//元素每次拖动开始时,记录它的坐标(偏移量)
oImg.ondragstart = function (e) {
offsetX = e.offsetX;
offsetY = e.offsetY;
};
//元素拖动过程中,重新设置它的坐标(偏移量)
oImg.ondrag = function (e) {
if (e.pageX === 0 && e.pageY === 0) {
return;
}
oImg.style.left = (e.pageX - offsetX) + "px";
oImg.style.top = (e.pageY - offsetY) + "px";
}
}
</script>
</head>
<body>
<img src="test.png" alt="" draggable="true"/>
</body>
</html>
效果图:
说明:
当图片拖动开始时,会触发ondragstart事件,此时我们使用offsetX、offsetY这两个变量记录图片初始坐标。当图片被拖动时,会触发ondrag事件,此时我们重新设置图片的位置。其中,e.offsetX、e.offsetY分别表示鼠标相对于触发事件的对象的X坐标、Y坐标,e.pageX、e.pageY分别表示鼠标相对于当前窗口的X坐标、Y坐标。
2、dataTransfer对象
2.1、dataTransfer对象简介
在HTML5中,如果想要在元素拖放中实现数据传递,我们需要使用dataTransfer对象。dataTransfer对象主要用于在“源元素”与“目标元素”之间传递数据。dataTransfer对象有两个最重要的方法:setData()和getData()。在整个拖拽过程中,具体操作是这样的:开始拖放源元素时(ondragstart事件),调用setData()方法保存数据;然后在放入目标元素时(ondrop事件),调用getData()方法读取数据。
2.1.1、setData()方法
在拖放操作中,我们可以使用setData()方法保存数据。
语法:
setData(format, data);
参数format表示数据格式,常见的数据格式如下表所示:
数据格式 | 说明 |
---|---|
text/plain | 文本文字格式 |
text/html | HTML代码格式 |
text/xml | XML字符格式 |
text/url-list | URL列表格式 |
举例:
source.ondragstart = function (e) {
e.dataTransfer.setData("text/plain", e.target.id);
}
2.1.2、getData()方法
在拖放操作中,我们可以使用getData()方法读取数据。
语法:
getData(format);
参数format表示数据格式,数据格同2.1.1表格。
举例:
dest.ondrop = function (e) {
e.dataTransfer.getData("text/plain");
}
2.2、dataTransfer对象应用
dataTransfer对象在元素拖拽的应用开发中使用非常广泛,下面举几个经典的实际案例进行说明:
2.2.1、举例1:元素拖动效果
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
ul {
width: 120px;
height: 120px;
border: 1px solid silver;
}
</style>
<script>
window.onload = function () {
const oList = document.getElementById("list");
const oLi = oList.getElementsByTagName("li");
const oBox = document.getElementById("box");
//为每一个li(源元素)添加ondragstart事件
for (let i = 0; i < oLi.length; i++) {
oLi[i].ondragstart = function (e) {
e.dataTransfer.setData("text/plain", e.target.id);
};
}
//调用event.preventDefault()方法来屏蔽元素的默认行为,否则drop事件不会被触发!
oBox.ondragover = function (e) {
e.preventDefault();
};
//为目标元素添加ondrop事件
oBox.ondrop = function (e) {
e.preventDefault();
const id = e.dataTransfer.getData("text/plain");
const obj = document.getElementById(id);
oBox.appendChild(obj);
};
}
</script>
</head>
<body>
<ul id="list">
<li draggable="true" id="li1">HTML5</li>
<li draggable="true" id="li2">CSS3</li>
<li draggable="true" id="li3">JavaScript</li>
<li draggable="true" id="li4">jQuery</li>
<li draggable="true" id="li5">Vue</li>
</ul>
<ul id="box"></ul>
</body>
</html>
效果图:
分析说明:
for (let i = 0; i < oLi.length; i++) {
oLi[i].ondragstart = function (e) {
e.dataTransfer.setData("text/plain", e.target.id);
};
}
首先,我们为每一个li元素添加ondragstart事件,e.dataTransfer表示获取dataTransfer对象,e.target.id表示获取当前事件的元素的id值。
oBox.ondragover = function (e) {
e.preventDefault();
};
上面这段代码表示调用event.preventDefault()方法来屏蔽元素的默认行为。如果没有屏蔽掉,则drop事件不会被触发。
oBox.ondrop = function (e) {
e.preventDefault();
const id = e.dataTransfer.getData("text/plain");
const obj = document.getElementById(id);
oBox.appendChild(obj);
};
最后,我们为目标元素box添加ondrop事件,并且在ondrop事件中使用getData()方法获取元素的id值,从而使用DOM操作把li元素添加到box中。此外,e.preventDefault()也是用于屏蔽元素的默认行为,e.dataTransfer.getData(“text/plain”)表示调用dataTransfer对象的getData()方法获取数据。
2.2.2、举例2:垃圾箱效果
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
#bigBox {
display: inline-block;
width: 100px;
height: 100px;
background-color: green;
}
#smallBox {
display: inline-block;
width: 50px;
height: 50px;
background-color: gray;
}
</style>
<script>
window.onload = function () {
const oBigBox = document.getElementById("bigBox");
const oSmallBox = document.getElementById("smallBox");
oSmallBox.ondragstart = function () {
};
oBigBox.ondragover = function (e) {
e.preventDefault();
};
oBigBox.ondrop = function (e) {
e.preventDefault();
oSmallBox.parentNode.removeChild(oSmallBox);
};
}
</script>
</head>
<body>
<div id="bigBox"></div>
<div id="smallBox" draggable="true"></div>
</body>
</html>
效果图:
分析说明:
oSmallBox.ondragstart = function () {};
首先,我们为smallBox元素添加ondragstart事件,由于这里ondragstart内部不需要做什么操作,所以可以删除该事件。
oBigBox.ondragover = function (e) {
e.preventDefault();
};
上面这段代码表示调用event.preventDefault()方法来屏蔽元素的默认行为。如果没有屏蔽掉,则drop事件不会被触发。
oBigBox.ondrop = function (e) {
e.preventDefault();
oSmallBox.parentNode.removeChild(oSmallBox);
};
最后,我们为目标元素bigBox添加ondrop事件,并且在ondrop事件中通过smallBox的父节点删除当前的smallBox节点。最终效果就是当我们将smallBox元素拖动到bigBox元素中时,smallBox元素就会被删除。
从上面两个例子可以知道,想要实现拖拽效果,一般情况下我们需要操作3个事件:ondragstart、ondragover和ondrop。如果某一个事件不涉及什么操作,也可以不写。
- 点赞
- 收藏
- 关注作者
评论(0)