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); }; }; |