通常我们在上传文件时,需要使用 <input type="file"/> 这样的上传文件标签。而在html5中,它提供了拖放的接口,以下的内容就是对html5拖放的一些事件进行详细的解释和说明,并做了一些简单的应用:

其实可以先来看几个demo:单个元素拖放多个元素交换元素的删除多上传文件

上面的demo中涉及到的元素主要有 拖放元素 和 目标元素,下面分别说说它们:

被拖放元素

首先,如果使得一个元素能够拖动,就必须让元素有draggable=”true”属性,针对被拖动元素有下列事件:

事件 说明
dragstart 被拖拽的元素拖拽前进行触发的事件
drag 被拖拽的元素拖拽开始与拖拽结束之间连续触发的事件
dragend 被拖拽的元素拖拽结束时,触发的事件

实例

知道了以上的知识点,我们可以做了一个简单的实例,这个实例是对一个元素拖放时背景颜色的变化,并在它里面显示拖放的状态:

被拖动的元素拖动过程
<style>
#drag_box{width:100px;height:100px;background:#ccc;}
</style>


<div id="drag_box" draggable="true"></div>

<script>
(function(){
function $(id){
return document.getElementById(id);
}
var oDrag=$("drag_box");
oDrag.ondragstart=function(){
this.style.background="green";
   if(navigator.userAgent.toLowerCase().indexOf("msie")==-1){
    ev.dataTransfer.setData('elem',oDrag);// 设置数据类型,否则firefox拖动无效
   }
}
oDrag.ondrag=function(){
this.innerHTML="拖拽中...";
}
oDrag.ondragend=function(){
this.style.background="#f55";
this.innerHTML="拖拽结束";
}
})();
</script>

目标元素

拖拽元素对应的是目标元素,它也有如下事件:

事件 说明
dragenter 被拖拽元素进入目标元素所触发的事件
dragover 被拖拽元素进入目标元素之后,离开目标元素之前所连续触发的事件
dragleave 被拖拽元素离开目标元素触发的事件
drop 在目标元素上释放鼠标触发的事件(也就是把被拖放元素放入目标元素中)

实例

这个实例,分别记录了被拖放元素在进入和离开目标元素,还有在目标元素里移动以及释放的各种状态,如下:

在目标元素里的拖放
<style>
#drag_box{width:100px;height:100px;background:#ccc;float:left;}
#target_box{width:200px;height:200px;background:#ccc;margin-left:150px;line-height:200px;text-align:center;}
</style>


<div id="drag_box" draggable="true"></div>
<div id="target_box"></div>

<script>
(function(){
function $(id){
return document.getElementById(id);
}
var oDrag=$("drag_box"),oTarget=$("target_box");
oDrag.ondragstart=function(ev){
this.style.background="green";
   if(navigator.userAgent.toLowerCase().indexOf("msie")==-1){
    ev.dataTransfer.setData('elem',oDrag);
   }
 }
oDrag.ondragend=function(){
this.style.background="#ccc";
}
oTarget.ondragenter=function(){
this.style.background="#fc0"
}
oTarget.ondragover=function(ev){
this.innerHTML="在元素中移动!"
ev.preventDefault(); //在这个过程一定,要加阻止默认事件,否则不能触发drop
}
oTarget.ondragleave=function(){
this.innerHTML="";
this.style.background="#ccc"
}
oTarget.ondrop=function(){
this.innerHTML="在目标元素里释放了!"
}
})();
</script>

dataTransfer对象

前面的内容只是大体的介绍了些拖拽和拖放的事件,并做了两个实例。但是这不是我们最终的目的,最终的目的当然是在拖动过程中实现数据的交换。

dataTransfer对象有两个主要方法:setData()和getData()。它们的具体使用如下:

ev.dataTransfer.setData(dataType,value);

在拖放元素时把要拖动的数据存入dataTransfer对象中,它有两个函数,第一个参数是数据类型,第二个参数为携带的数据。

ev.dataTransfer.getData(dataType);

getData()可以在drop的过程中取得由setData()保存的值。只有一个参数,即所存储的数据类型。

除了以上两个方法外,dataTransfer还有一个setDragImage 方法。

setDragImage(element,x,y);

它表示可以用一个图片来设置鼠标拖动的图标(类似css里面的cursor),当然这里不单只是图标,也可以是其他元素,比如说自身;

另外,dataTransfer对象有一个属性:effectAllowed,它规定被拖动元素拖入目标元素时,鼠标的样式,属性值有如下;

ev.dataTransfer.effectAllowed=CursorStyle;

CursorStyle的取值有 uninitialized ,none ,copy,link,move,copyLink,copyMove,linkMove,all。作用如下:

属性 描述
uninitialized 没有该被拖动元素放置行为
none 被拖动的元素不能有任何行为
copy 只允许值为”copy”的dropEffect
link 只允许值为”link”的dropEffect
move 只允许值为”move”的dropEffect
copyLink 允许值为”copy”和”link”的dropEffect
copyMove 允许值为”copy”和”link”的dropEffect
linkMove 允许值位”link”和”move”的dropEffect
all 允许任意dropEffect

实例

这个实例是将列表拖入目标元素并进行删除。而且在拖动被拖动元素时设置了鼠标拖动的图标,并且拖入到目标元素也改变了鼠标样式。

拖动删除列表
<style>
#drag_box{width:100px;height:100px;float:left;}
#target_box{width:200px;height:200px;background:#ccc;margin-left:150px;line-height:200px;text-align:center;}
</style>


<ul id="drag_box">
<li draggable="true">111</li>
<li draggable="true">222</li>
<li draggable="true">333</li>
</ul>
<div id="target_box"></div>

<script>
(function(){
function $(id){
return document.getElementById(id);
}
var oDrag=$("drag_box"),oTarget=$("target_box"),aLi=oDrag.getElementsByTagName("li"),removeEle=null,oImg=document.createElement("img");
oImg.src="logo.png";

for(var i=0;i<aLi.length;i++){
aLi[i].ondragstart=function(ev){
this.style.background="green";
if(navigator.userAgent.toLowerCase().indexOf("msie")==-1){
ev.dataTransfer.setData("text",ev.target.innerHTML);
removeEle=ev.target;
ev.dataTransfer.effectAllowed="copyLink";
ev.dataTransfer.setDragImage(oImg,0,0);
}
}
aLi[i].ondragend=function(){
this.style.background="#ccc";
}
}

oTarget.ondragenter=function(){
this.style.background="#fc0"
}

oTarget.ondragover=function(ev){
this.innerHTML="在元素中移动!"
ev.preventDefault();
}

oTarget.ondrop=function(ev){
ev.preventDefault();
this.innerHTML="元素已被删除!";
document.title=typeof removeEle;
oDrag.removeChild(removeEle);
}
})();
</script>

files对象

在html5中,关于拖动api里还介绍了一个files对象。该对象主要是为浏览器读取拖动到浏览器里的外部文件信息和内容提供了接口。并且该对象的所有事件都是在拖动文件释放到目标元素后才执行的,也就是说都是在drop里面触发的。以下对files对象的相关属性和方法进行介绍:

获取外部拖动文件信息,返回的是一个拖动文件的列表:

ev.dataTransfer.files;

读取外部拖动文件信息,首先要创建读取对象,然后读取文件信息的url。当读取成功后,此时在对象onload下可以通过result来得到读取文件的信息内容,最后进行相关操作:

files=ev.dataTransfer.files;
filesReader=new FileReader();
filesReader.readAsDataURL(files[0]);
filesReader.onload=function(){
var obj=document.createElement("elem");
obj.src=this.result;
//do something
}

实例

该实例利用files对象来拖动外部文件到浏览器。

拖动外部文件添加到浏览器
<style>
#target_box{width:100px;height:100px;background:#ccc;line-height:100px;text-align:center;font-size:12px;}
img{width:80px;height:50px;display:block;margin:10px;
</style>


<div id="target_box"></div>

<script>
(function(){
function $(id){
return document.getElementById(id);
}
var oTarget=$("target_box");

oTarget.ondragenter=function(){
this.style.background="#fc0"
}

oTarget.ondragover=function(ev){
this.innerHTML="在元素中移动!"
ev.preventDefault();
}
oTarget.ondrop=function(ev){
ev.preventDefault();
this.innerHTML="元素已添加!";
var files=ev.dataTransfer.files;
for(var i=0;i<files.length;i++){
var filesReader=new FileReader();
filesReader.readAsDataURL(files[i]);
filesReader.onload=function(){
var oImg=document.createElement("img");
oImg.src=this.result;
document.body.appendChild(oImg);
}
}
}
})();
</script>

最后关于html5拖动API,还有一些内容不是太理解,比如dataTransfer对象里数据的设置及参数和数据的读取,还有当把被拖动元素拖到目标元素释放时,在firefox浏览器中会默认打开新窗口,希望找到相关内容进行更多的了解。