隨着HTML5的普及度越來越高,現在寫代碼也遇到一些了,經過同事的點播開展了一次Dojo活動用以技術交流,我也乘此機會將HTML5的拖放功能整理了一下。
簡介
拖拽(Drag/Drop)是個非常普遍的功能。在生活中,拖放物品其實是相當常見的一個動作。標榜“互聯網生活尖鑿獅”的程序猿也在一直試圖用鼠標模擬出“手”的操作,用來給用戶以更好的體驗,你可以抓住一個對象,並且拖動到你想放置的區域。很多javascript都類似實現了相關的功能,例如,jQueryUI的draganddrop組件,比如《JS實現頁面拖放》。。在HTML5中,拖拽(draganddrop)成為了標准操作,任何元素都支持。
定義
拖放是一種常見的特性,即抓取對象以后拖到另一個位置。
在 HTML5 中,拖放是標准的一部分,任何元素都能夠拖放。
瀏覽器支持
雖然是HTML5的東西,但是,根據findmebyip中顯示的瀏覽器支持情況來看,IE6~IE8都是有drag & drop API的(見下截圖)。
Internet Explorer 6~9、Firefox、Opera 12、Chrome 以及 Safari 5 支持拖放。
注釋:在 Safari 5.1.2 中不支持拖放。
根據自己的簡單的測試,低版本的IE瀏覽器確實支持諸如ondragstart事件,但是會報不認識dataTransfer的錯誤。可見IE在細節的處理上與現代瀏覽器有些不同。
HTML5 拖放實例
下面的例子是一個簡單的拖放實例:
<script type="text/javascript"> function allowDrop(ev) { ev.preventDefault(); } function drag(ev) { ev.dataTransfer.setData("Text",ev.target.id); } function drop(ev) { ev.preventDefault(); var data=ev.dataTransfer.getData("Text"); ev.target.appendChild(document.getElementById(data)); } </script> </head> <body> <div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div> <img id="drag1" src="http://www.baidu.com/img/baidu_jgylogo3.gif" draggable="true" ondragstart="drag(event)" width="336" height="69" /> </body>
它看上去也許有些復雜,不過我們可以分別研究拖放事件的不同部分。
設置元素為可拖放
首先,為了使元素可拖動,把 draggable 屬性設置為 true :
<img draggable="true" />
拖動什么 - ondragstart 和 setData()
然后,規定當元素被拖動時,會發生什么。
在上面的例子中,ondragstart 屬性調用了一個函數,drag(event),它規定了被拖動的數據。
dataTransfer.setData() 方法設置被拖數據的數據類型和值:
function drag(ev) { ev.dataTransfer.setData("Text",ev.target.id); }
在這個例子中,數據類型是 "Text",值是可拖動元素的 id ("drag1")。
放到何處 - ondragover
ondragover 事件規定在何處放置被拖動的數據。
默認地,無法將數據/元素放置到其他元素中。如果需要設置允許放置,我們必須阻止對元素的默認處理方式。
這要通過調用 ondragover 事件的 event.preventDefault() 方法:
event.preventDefault()
進行放置 - ondrop
當放置被拖數據時,會發生 drop 事件。
在上面的例子中,ondrop 屬性調用了一個函數,drop(event):
function drop(ev) { ev.preventDefault(); var data=ev.dataTransfer.getData("Text"); ev.target.appendChild(document.getElementById(data)); }
代碼解釋:
- 調用 preventDefault() 來避免瀏覽器對數據的默認處理(drop 事件的默認行為是以鏈接形式打開)
- 通過 dataTransfer.getData("Text") 方法獲得被拖的數據。該方法將返回在 setData() 方法中設置為相同類型的任何數據。
- 被拖數據是被拖元素的 id ("drag1")
- 把被拖元素追加到放置元素(目標元素)中
拖放(Drag 和 Drop)各屬性生命周期
剛才大家已經看到了一些新鮮屬性名詞,如 ondragstart。或許還是很陌生,不知其所以,下面看一張表格或許能豁然開朗:
拖動生命周期 | 屬性 | 值 | 描述 |
拖動開始 | ondragstart | script | 在拖動操作開始時執行腳本(對象是被拖拽元素) |
拖動過程中 | ondrag | script | 只要腳本在被拖動就允許腳本(對象是被拖拽元素) |
拖動過程中 | ondragenter | script | 當元素被拖動到一個合法的放置目標時,執行腳本(對象是目標元素) |
拖動過程中 | ondragover | script | 只要元素正在合法的放置目標上拖動時,就執行腳本(對象是目標元素) |
拖動過程中 | ondragleave | script | 當元素離開合法的放置目標時(對象是目標元素) |
拖動結束 | ondrop | script | 將被拖拽元素放在目標元素內時運行腳本(對象是目標元素) |
拖動結束 | ondragend | script | 在拖動操作結束時運行腳本(對象是被拖拽元素) |
寫在哪呢?
其實參照上表“描述”中括號內的提示即可知道,不過為了能更直觀的了解到,特呈上代碼:
被拖放元素
<span draggable="true" id="Span1" ondragstart="fooDragStart(this, event)" ondrag="fooDrag(this, event)" ondragend="fooDragEnd(this, event)"> <img src="../images/yjj_1.png"></span>
目標元素
<div id="div1" ondrop="fooDrop(this, event)" ondragenter="fooDragEnter(this, event)" ondragleave="fooDragLeave(this, event)" ondragover="fooDragOver(this,event)"> </div>
執行順序
下面,我將展示將一張圖片放入div中的整個script執行過程:
執行元素介紹
執行結果
1. 成功將圖片拖入div中
onDragStart,當元素被拖動到一個合法的放置目標時,執行腳本(對象是目標元素)
onDrag,只要腳本在被拖動就允許腳本
onDrag,只要腳本在被拖動就允許腳本
onDragEnter,在拖動操作開始時執行腳本
onDragOver,只要元素正在合法的放置目標上拖動時,就執行腳本(對象是目標元素)
onDrag,只要腳本在被拖動就允許腳本
onDragOver,只要元素正在合法的放置目標上拖動時,就執行腳本(對象是目標元素)
onDrop,在拖動操作結束時運行腳本
onDragEnd,在拖動操作結束時運行腳本
2. 已拖放,可最終未放入div中
onDragStart,當元素被拖動到一個合法的放置目標時,執行腳本(對象是目標元素)
onDrag,只要腳本在被拖動就允許腳本
onDrag,只要腳本在被拖動就允許腳本
onDragEnter,在拖動操作開始時執行腳本
onDragOver,只要元素正在合法的放置目標上拖動時,就執行腳本(對象是目標元素)
onDrag,只要腳本在被拖動就允許腳本
onDragOver,只要元素正在合法的放置目標上拖動時,就執行腳本(對象是目標元素)
onDrag,只要腳本在被拖動就允許腳本
onDragLeave,當元素離開合法的放置目標時(對象是目標元素)
onDrag,只要腳本在被拖動就允許腳本
onDrag,只要腳本在被拖動就允許腳本
onDragEnd,在拖動操作結束時運行腳本
由上兩個執行順序的Log能看出:
- 只有將“被拖拽元素”放入“目標元素”才會執行“onDrop”屬性的方法;
- “onDrag”的事件只要鼠標按住並且拖動就會持續不斷的執行;
- “onDragOver”的事件是只要鼠標按住、拖動“被拖拽元素”在“目標元素”上滑過就會持續不斷的執行;
- “onDragEnd”的事件無論如何,只要按住的鼠標放開了,就會執行
小結
能讀到這里說明你是比較勤勞的了,看我嘮嘮叨叨。
在第一步我也只是介紹了HTML5 拖放(Drag 和 Drop)的基本功能,一些深入的比如“文件的拖放”、“從瀏覽器拖放到桌面”以及“從桌面拖放到瀏覽器”會在今后的文章中一一講解。
感謝閱讀。文中要是有表述不准確的地方,歡迎指正。