元素拖放 Drag
元素拖放简介
在 HTML5 之前,如果想要实现一个元素的拖放效果,我们一般需要结合该元素的 onmousedown、onmousemove、onmouseup 等多个事件来共同完成。这种方式代码量非常大,而且也仅限于在浏览器内的元素间拖放,不能实现跨应用拖放。
在 HTML5 中,我们只需要给元素添加一个 draggable 属性,然后设置该属性值为 true,就能实现元素的拖放。拖放,指的是“拖曳”和“释放”。在页面中进行一次拖放操作,我们必须先弄清楚两个元素:“源元素”和“目标元素”。“源元素”指的是被拖曳的那个元素,“目标元素”指的是源元素最终被释放到的那个元素。
如果仅给元素设置 draggable=“true”,则该元素只具备可拖曳的特点,并不能改变元素的位置。如果想要拖动改变元素的位置,我们还需要结合元素拖放触发的事件来操作。其中,拖放事件总共有 7 个
- 源元素触发的事件
- 目标元素触发的事件
一个完整的拖放事件过程如图:
举例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
body {
position: relative;
}
img {
position: absolute;
}
</style>
<script>
window.onload = function () {
var oImg = document.getElementsByTagName("img")[0];
var 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="pic.png" alt="" draggable="true" />
</body>
</htm
元素拖放
分析:
当图片拖动开始时,会触发 ondragstart 事件,此时我们使用 offsetX、offsetY 这两个变量记录图片初始坐标。当图片被拖动时,会触发 ondrag 事件,此时我们重新设置图片的位置。
其中,e.offsetX、e.offsetY 分别表示鼠标相对于触发事件的对象的 X 坐标、Y 坐标,e.pageX、e.pageY 分别表示鼠标相对于当前窗口的 X 坐标、Y 坐标。
dataTransfer对象
- dataTransfer 对象简介
在 HTML5 中,如果想要在元素拖放中实现数据传递,我们需要使用 dataTransfer 对象。dataTransfer 对象主要用于在“源元素”与“目标元素”之间传递数据。
dataTransfer对象有两个最重要的方法:setData() 和 getData()。在整个拖曳过程中,具体操作是这样的:开始拖放源元素时(ondragstart事件),调用 setData() 方法保存数据;然后在放入目标元素时(ondrop事件),调用 getData() 方法读取数据。
- setData() 方法
在拖放操作中,我们可以使用 setData() 方法保存数据。
setData(format, data);
参数format表示数据格式,常见的数据格式如表:
举例:
source.ondragstart=function(e){
e.dataTransfer.setData("text/plain",e.target.id);
};
- getData() 方法
在拖放操作中,我们可以使用 getData() 方法读取数据。
getData(format);
参数format表示数据格式
举例:
dest.ondrop=function(e){
e.dataTransfer.getData("text/plain");
};
- dataTransfer 对象应用
dataTransfer 对象在元素拖曳的应用开发中使用非常广泛,
举例:元素拖拽效果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
ul {
width: 120px;
height: 100px;
border: 1px solid silver;
}
</style>
<script>
window.onload = function () {
var oList = document.getElementById("list");
var oLi = oList.getElementsByTagName("li");
var oBox = document.getElementById("box");
//为每一个li(源元素)添加ondragstart事件
for (var 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();
var id = e.dataTransfer.getData("text/plain");
var obj = document.getElementById(id);
oBox.appendChild(obj);
};
};
</script>
</head>
<body>
<ul id="list">
<li draggable="true" id="li1">HTML</li>
<li draggable="true" id="li2">CSS</li>
<li draggable="true" id="li3">JavaScript</li>
<li draggable="true" id="li4">jQuery</li>
<li draggable="true" id="li5">Vue.js</li>
</ul>
<ul id="box"></ul>
</body>
</html>
分析:
for (var 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();
var id = e.dataTransfer.getData("text/plain");
var obj = document.getElementById(id);
oBox.appendChild(obj);
};
最后,我们为目标元素 oBox 添加 ondrop 事件,并且在 ondrop 事件中使用 getData() 方法获取元素的id值,从而使用 DOM 操作把 li 元素添加到 oBox 中。
此外,e.preventDefault() 也是用于屏蔽元素的默认行为,e.dataTransfer.getData(“text/plain”) 表示调用 dataTransfer 对象的 getData() 方法获取数据。
举例:垃圾箱效果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
#bigBox {
display: inline-block;
width: 100px;
height: 100px;
background-color: hotpink;
}
#smallBox {
display: inline-block;
width: 50px;
height: 50px;
background-color: lightskyblue;
}
</style>
<script>
window.onload = function () {
var oBigBox = document.getElementById("bigBox");
var 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>
分析:
当我们将 smallBox 元素拖动到 bigBox 元素中时,smallBox 元素就会被删除。