最早在網頁中引入JavaScript拖放功能的是IE4,當時網頁只有兩種對象可以拖放:圖像的文本。在HTML5中提供了拖拽的API,使得任意元素都可以實現拖放,當我們在網頁上拖放某個元素的時候將會依次觸發以下事件:
1、ondragstart--開始拖動元素時觸發
2、ondrag--按住左鍵,拖動元素時觸發
3、ondragend--釋放左鍵,結束拖動時觸發
當釋放某個元素時將會依次觸發以下時間:
1、ondragenter--拖動元素開始進入容器時觸發
2、ondragover--拖動元素進入容器,拖動時觸發
3、ondragleave--拖動元素離開容器時觸發
4、ondrop--釋放拖動元素時觸發,優先ondragend觸發
PS:在默認情況下,一個元素是不能放置到另一個元素里的,如果要實現拖放的功能,則需要在ondragover事件中需要加上event.preventDefault()阻止默認行為,否則ondrop就不會執行了
dataTransfer對象
在實現拖放效果的時候並且要發生數據的變化,在IE5中引入了dataTransfer對象,它是事件對象的一個屬性,用於拖動元素向容器傳遞字符串格式數據,使用這個對象的屬性和方法可以用來完善拖放功能。
dataTransfer對象有兩個主要方法:getData()和setData()。getData()用於獲取setData()保存的值。setData()方法的第一個參數也是getData()方法唯一的一個參數,為字符串類型,表示保存的數據類型,在IE中指定義了'text'或者'URL'兩種有效類型,而在HTML5中是允許指定各種MIME類型,這兩種類型會被映射為'text/plain'和'text/uri-list',用法如下:
//設置和接收字符串 event.dataTransfer.setData('text/plain','some text'); var text = event.dataTransfer.getData('text/plain'); //設置和接收URL event.dataTransfer.setData('text/uri-list','http://www.cnblogs.com/weapon-x/'); var url= event.dataTransfer.getData('text/uri-list');
實際上,dataTransfer對象可以為每種MIME類型保存一個值,就是說可以同時在對象上保存一段文本和一段URL,保存在對象中的數據只能在drop時間處理程序中去讀取了。
利用dataTransfer對象不光能夠傳輸數據,還能通過它來確定被拖動元素以及作為放置的目標的元素能接受什么操作,需要訪問:dropEffect和effectAllowed這兩個屬性,具體可以查一下API哈。
好了,有了以上的知識前提下,我寫了一個簡單的demo,代碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .interest-box{ width: 300px; height: 100px; border:1px solid #eee; list-style: none; } .interest-box li{ width: 50px; line-height: 30px; border-radius: 5px; border:1px solid #1d7db1; text-align: center; float:left; margin-right: 10px; cursor: pointer; -webkit-user-select: none; } #trash{ width: 100px; height: 100px; border: 1px solid #ccc; } </style> </head> <body> <p>選擇自己的興趣愛好</p> <ul class="interest-box"> <li class="interest" draggable="true">音樂</li> <li class="interest" draggable="true">運動</li> <li class="interest" draggable="true">電影</li> <li class="interest" draggable="true">code</li> </ul> <p>我的興趣:</p> <ul id="my-interest" class="interest-box"></ul> <p>垃圾桶</p> <div id="trash"></div> <script> window.onload = function(){ var $li = document.getElementsByTagName('li'), $mi = document.getElementById('my-interest'), $trash = document.getElementById('trash'); for(var i= 0,length = $li.length;i<length;i++){ //為每個li添加ondragstart事件 $li[i].ondragstart = function(e) { //存儲innerHTML e.dataTransfer.setData('text/plain','<li>'+ e.target.innerHTML); } } $mi.ondragover = function(e){ //阻止默認行為 e.preventDefault(); } $mi.ondrop = function(e){ //獲取數據 var html = e.dataTransfer.getData('text/plain'); if(html.indexOf('<li>')==0){ var _li = document.createElement('li'); //創建新元素 _li.id = (new Date()).getTime(); //生成唯一ID _li.draggable = true; _li.innerHTML = html.substring(4); //字符串截取 $mi.appendChild(_li); //添加ondragstart _li.ondragstart = function(e){ e.dataTransfer.setData('text/plain','<id>'+_li.id); } } } $trash.ondragover = function(e){ //阻止默認行為 e.preventDefault(); } $trash.ondrop = function(e){ var _id = e.dataTransfer.getData('text/plain'); if(_id.indexOf('<id>')==0){ var target = document.getElementById(_id.substring(4)); $mi.removeChild(target); //刪除節點 } } } </script> </body> </html>
截圖如下:
最后查了一下拖放在各大瀏覽器的支持情況,在IE8往后都是部分支持,在實際項目中我也沒有做過拖放的需求,不是很清楚支持的情況,而在手機端就全軍覆沒了呢
如果文中出現錯誤,歡迎大家指正:)