1. 给标签元素添加属性:draggable = “true”,该元素即可被拖拽,任何元素都可以被拖拽
特点:拖走的是灵魂
2. 事件
(1)可拖拽元素的事件
dragstart事件:被拖拽元素,开始被拖拽时触发
dragend事件:被拖拽元素,拖拽完成时触发
注意:e.target对象上,是拖拽元素的所有信息,包括属性、方法、对象等。需要了解一下:
(2)目标元素事件
dragenter事件:目标元素的事件,被拖拽元素进入目标元素时触发
dragover事件:目标元素的事件,被拖拽元素在目标元素上移动时触发
var oDiv1 = document.getElementsByTagName('div')[0];
var oDiv2 = document.getElementsByTagName('div')[1];
oDiv2.ondragenter = function(){
console.log("拖拽元素进去目标元素...");
}
oDiv2.ondragover = function(){
console.log("拖拽元素在目标元素中移动");
}
drop事件:目标元素事件,被拖拽元素拖到目标元素上松开鼠标时触发
var oDiv1 = document.getElementsByTagName('div')[0];
var oDiv2 = document.getElementsByTagName('div')[1];
oDiv2.addEventListener('dragover', function (e) {
cancelHandler(e);
console.log("取消dragover事件");
}, false);
oDiv2.addEventListener('drop', function () {
console.log("拖拽元素进入目标元素后,松开鼠标");
}, false);
//兼容性的取消默认事件
function cancelHandler(e) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}
注意:判断元素的位置,是由元素上鼠标的位置决定的。
注意:需要取消dragover默认事件,dragover事件还会触发,只是取消了默认事件?才能触发drop事件
3. DragEvent事件
目标元素上的dragenter、dragover、drop事件,无法区别到底是哪一个拖拽元素,触发了目标元素的事件,可以通过传值和取值,来区分拖拽元素
英语:dataTransfer:数据传递
传值:被拖拽元素将值设置在“传输通道”中
取值:目标元素从“传输通道”中取值,拖拽元素和目标元素建立传输通道,就是将拖拽元素拖拽到目标元素上。
注意:传输通道中的值,无法查看。e.dataTransfer:传输通道中竟然不能查看到设置的值
<div id="drag1" draggable="true">拖拽元素1</div>
<div id="drag2" draggable="true">拖拽元素2</div>
<div id="target">目标元素</div>
<script>
drag1.ondragstart = function(e){
e.dataTransfer.setData('data', this.id);//设置值
}
target.addEventListener('dragover', function(e){
e.preventDefault();
},false)
target.ondrop = function(e){
console.log(e.dataTransfer);//传输通道中竟然不能查看到设置的值
console.log(e.dataTransfer.getData('data'));//获取值
}
</script>
实例:列表排序和删除
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>test</title>
<style>
*{
padding: 0px;
margin: 0px;
list-style: none;
}
.demo{
width: 300px;
height: 300px;
border: 1px solid black;
margin-left: 50px;
}
.demo ul li{
width: 200px;
height: 50px;
background-color: #888;
border: 1px solid #000;
margin-bottom: 5px;
cursor: pointer;
text-align: center;
line-height: 50px;
color: #fff;
}
.wrapper{
width: 300px;
height: 300px;
border: 1px solid black;
margin-left: 50px;
}
</style>
</head>
<body>
<div class="demo">
<ul>
<li draggable="true">111</li>
<li draggable="true">222</li>
<li draggable="true">333</li>
<li draggable="true">444</li>
<li draggable="true">555</li>
</ul>
</div>
<div class="wrapper">将列表拖到此处移除</div>
<script>
var oLi = document.getElementsByTagName('li');
var len = oLi.length;
var oUl = document.getElementsByTagName('ul')[0];
var oWrap = document.getElementsByClassName('wrapper')[0];
function bindLiEvent(){
for(var i = 0; i < len; i++){
oLi[i].addEventListener('dragstart', function(e){
var index = getIndex(this);
e.dataTransfer.setData('data', index);
}, false)
oLi[i].addEventListener('dragover', function(e){
e.preventDefault();
}, false);
oLi[i].addEventListener('drop', function(e){
var i = e.dataTransfer.getData('data');
//此处的i是有上面dragstart事件的i,所以oLi[i]中的i决定了该值。
console.log(oLi[i]);
//此处的this是该事件对象
console.log(this);
oUl.insertBefore(oLi[i], this);
}, false);
}
}
function getIndex(dom){
for(var i = 0; i < len; i++){
if(oLi[i] === dom){
return i;
}
}
}
function removeLi(){
oWrap.addEventListener('dragover', function(e){
e.preventDefault();
}, false);
oWrap.addEventListener('drop', function(e){
var index = e.dataTransfer.getData('data');
oLi[index].remove();
}, false);
}
bindLiEvent();
removeLi();
</script>
</body>
</html>
4. e.dataTransfer上有哥属性:files,是对文件信息的描述
该事件绑定在目标元素上,当浏览器之外的文件,拖入到浏览器的目标元素上时,浏览器会默认打开该文件,所以,要在drop事件中取消默认事件,即可防止浏览器打开文件。(浏览器可以打开很多类型的文件)
例子:将外部文件拖入到粉红色区。
<div id="wrapper" style="width:200px;height:200px;background-color:pink;"></div>
<script>
wrapper.ondragover = function(e){
e.preventDefault();
}
wrapper.ondrop = function(e){
e.preventDefault();//取消默认事件,防止浏览器对文件进行默认处理
console.log(e.dataTransfer.files);
}
</script>