HTML5拖拽
一、传统实现拖拽的方式
传统的就是使用js实现元素的拖拽,核心原理如下:
#box{ width:100px; height:100px; background:red; /*实现拖拽的核心之一! 拖拽实质就是不断改变其定位,所以需要先设置为绝对定位 然后结合js不断改变其left和top的值即可实现拖拽*/ position:absolute; } <div id="box"></div>
window.οnlοad=function(){ varbox=document.getElementById("box"); box.onmousedown=function(){ box.onmousemove=function(event){ box.style.left=event.clientX+"px"; box.style.top=event.clientY+"px"; }; }; box.onmouseup=function(event){ box.style.left=event.clientX+"px"; box.style.top=event.clientY+"px"; }; }; |
二、HTML5实现拖拽
1.定义被拖拽对象
首先要创建被拖拽的对象,在html5中为被拖拽元素设置draggable属性即可定义元素是否允许拖拽。该属性有三个值:true:元素可以被拖拽;false:元素不能被拖拽;auto:浏览器自己判断元素是否能被拖拽。
例如:<div id="box2" draggable="true">我可以被拖拽</div>
此时元素只能被拖拽起来,但是并不能实现放置以及默认以复制的方式拖拽。
火狐和IE目前都不支持,只有Chrome和Opera支持。
2.处理拖拽事件
接下来就是处理拖拽事件了,HTML5支持的拖拽有三个,当我们拖拽对象的时候会触发拖拽事件有:
dragstart:当元素拖拽开始触发;
drag:在元素拖拽过程中触发;
dragend:元素拖拽结束时触发
以上三个事件在js中一般要使用on前缀,例如ondragstart、ondrag、ondragend。对于drag事件,在拖拽的过程中会不断的触发该事件,就好像间隔很短的时间就被触发一次一样的效果,即使拖拽到某个位置不再移动但是不放开鼠标,依然会不停的触发该事件。dragend事件是在放开鼠标的时候被触发。
例如:
<divid="box1">我接收被拖拽的对象</div> <divid="box2"draggable="true">我可以被拖拽</div>
window.οnlοad=function(){ varbox1=document.getElementById("box1"); varbox2=document.getElementById("box2"); box2.ondragstart=function(){ box1.innerHTML+="开始-"; }; box2.ondrag=function(){ //box1.innerHTML+="移动-"; }; box2.ondragend=function(){ box1.innerHTML+="完成<br>"; }; }; |
3.处理投放事件
拖拽结束后一定是将被拖拽元素放置到某个地方或进行一些拖拽完成的处理操作,此时就需要使用html5提供的投放事件,当拖拽对象进入投放区域就会触发投放事件。投放事件如下:
Ø dragenter:当拖拽对象进入投放区时触发;
Ø dragover:拖拽对象在投放区内移动时触发,其实不移动也会
Ø dragleave:拖拽对象没有投放到投放区,离开投放区的时候触发;
Ø drop:拖拽对象投放在投放区时触发,即放开鼠标时
这里定义进入和离开的触发时机是鼠标进入投放区域或离开投放区域时就触发,即何时触发决定于鼠标在被拖拽元素上哪个位置点击进行拖拽,此时被拖拽元素只要这个点(即鼠标)进入投放区域就会触发进入事件,而不是整个元素进入才触发。
dragenter、dragover可能会受到默认事件的影响,所以对于dragenter、dragover我们在这两个事件当中使用e.preventDefault();来阻止事件默认事件。
还要注意:投放事件使用投放元素来调用,而不是使用被拖拽元素调用的。
4.使用dataTransfer传递数据
在拖拽的时候可以给其它拖拽事件对象传递一些数据,例如拖拽开始时为拖拽事件对象设置一个参数,然后在完成拖拽时从完成拖拽这个事件对象取出这个参数。例如向投放区域传递拖拽对象的数据就可以使用这种方式实现,实际应用中有商品拖入购物车,那么就需要商品开始拖拽时传递商品参数到拖拽事件对象中,然后在投放到购物车的时候,使用购物车的投放事件对象获取该属性值。
这都是使用事件对象的dataTransfer对象来实现的,该对象有如下方法:
Ø getData(<format>):返回指定格式数据;
Ø setData(<format>,<data>):设置指定格式数据;
Ø clearData(<format>):移除指定格式数据;
Ø files:返回已经投放的文件的信息数组。
type:文件类型
size:文件大小
name:文件名
例如:
window.οnlοad=function(){ varbox1=document.getElementById("box1"); varbox2=document.getElementById("box2"); //处理拖拽 box2.ondragstart=function(e){ box1.innerHTML+="开始-"; //为拖拽对象传递参数,在后面的拖拽事件中可以通过事件对象获取该参数 //例如投放区域获取被拖拽对象的信息 e.dataTransfer.setData("info","哈哈哈"); }
//处理投放,注意是需要使用投放对象来调用而不是拖拽对象了 box1.ondragenter=function(e){ box1.innerHTML+="进入-"; e.preventDefault(); }; box1.ondragover=function(e){ //box1.innerHTML+="moveing-"; e.preventDefault(); }; box1.ondragleave=function(e){ box1.innerHTML+="离开"; e.preventDefault(); }; box1.ondrop=function(e){ box1.innerHTML+="完成"; e.preventDefault(); //结束时被拖拽元素放入投放区域中 box1.appendChild(box2); varinfo=e.dataTransfer.getData("info"); alert(info); }; }; |
三、拖拽异步上传
从系统从拖拽一个文件到浏览器默认的是打开该文件或提示保存该文件。此时要实现的是可以拖入一个文件但不是打开也不是保存,而是上传到服务端。
核心思想:利用HTML5提供的拖拽特定,从系统中拖拽一个或多个文件到浏览器页面的一个指定区域中(投放区域),并阻止浏览器的默认事件,然后利用HTML5的拖拽API获取文件的信息,之后再将该文件对象封装到一个form对象中,利用Ajax异步发送给服务端接收。
1.创建投放区域
投放区域就是文件拖拽进该区域后会自动异步上传,此时投放区域在html中只是简单的div等元素:
<divid="box">拖拽到这里上传</div> 样式: #box{ width:200px;height:200px; border:1px dashed black; text-align:center; line-height:200px; } |
2.创建js脚本,控制拖拽
window.onload = function() { varbox=document.getElementById("box"); /*由于浏览器默认的对拖拽进的文件是打开或提示打开或保存 所以在投放区域使用preventDefault()阻止该事件,但投放区外还是默认事件 并且阻止默认事件的代码要放到第一行,即首先阻止默认行为*/ box.οndragenter=function(e){ e.preventDefault(); }; box.οndragοver=function(e){ e.preventDefault(); box.innerHTML="松开鼠标开始上传"; }; box.οndragleave=function(e){ e.preventDefault(); box.innerHTML="拖拽到这里上传"; }; box.οndrοp=function(e){ e.preventDefault(); box.innerHTML="上传中..."; /**e.dataTransfer.files可以获取所投放的文件数组的信息 也就是说可以一次性拖入多个文件,该数组每个元素代表每个文件的详细信息*/ var files=e.dataTransfer.files; //alert(files.length); //获取拖入文件的个数 //获取投放的第一个文件的名称,size获取大小,type获取文件类型,... //alert(files[0].name); var file1=files[0];
/**由于使用form的input type=file可以实现文件上传,因此由于没有表单所以需要模拟出一个表达对象,js提供了FormData这个函数来模拟以一个表达对象*/ varformData=newFormData(); //相当于 <input type=file name='myfile' /> formData.append("myfile",file); //使用ajax异步上传,暂时不考虑兼容性 var xmlHttp=newXMLHttpRequest(); //必须使用post才能提交文件类型的数据,即大量的数据 xmlHttp.open("post","xxx.do"); //发送表单数据,然后服务端使用myfile这个名称接收即可 xml.send(formData); }; }; |