拖放(drap && drop)在咱們平時的工做中,常常遇到。它表示:抓取對象之後拖放到另外一個位置。目前,它是HTML5標準的一部分。我從幾個方面學習並實踐這個功能。html
咱們先看下拖放的流程:chrome
選中 ---> 拖動 ---> 釋放
而後,咱們一步步看下這個過程當中,會發生的事情。數組
在HTML5標準中,爲了使元素可拖動,把draggable屬性設置爲true。
文本、圖片和連接是默承認以拖放的,它們的draggable屬性自動被設置成了true。
圖片和連接按住鼠標左鍵選中,就能夠拖放。
文本只有在被選中的狀況下才能拖放。若是顯示設置文本的draggable屬性爲true,按住鼠標左鍵也能夠直接拖放。瀏覽器
draggable屬性:設置元素是否可拖動。
語法:<element draggable="true | false | auto" >
app
每個可拖動的元素,在拖動過程當中,都會經歷三個過程,拖動開始
-->拖動過程當中
--> 拖動結束
。學習
針對對象 | 事件名稱 | 說明 |
---|---|---|
被拖動的元素 | dragstart | 在元素開始被拖動時候觸發 |
drag | 在元素被拖動時反覆觸發 | |
dragend | 在拖動操做完成時觸發 | |
目的地對象 | dragenter | 當被拖動元素進入目的地元素所佔據的屏幕空間時觸發 |
dragover | 當被拖動元素在目的地元素內時觸發 | |
dragleave | 當被拖動元素沒有放下就離開目的地元素時觸發 |
dragenter和dragover事件的默認行爲是拒絕接受任何被拖放的元素。所以,咱們必須阻止瀏覽器這種默認行爲。e.preventDefault();flex
到達目的地以後,釋放元素事件ui
針對對象 | 事件名稱 | 說明 |
---|---|---|
目的地對象 | drop | 當被拖動元素在目的地元素裏放下時觸發,通常須要取消瀏覽器的默認行爲。 |
<!DOCTYPE HTML> <html> <head> <title>拖放示例-文本</title> </head> <style> .src { display: flex; } .dropabled { flex: 1; } .txt { color: green; } .img { width: 100px; height: 100px; border: 1px solid gray; } .target { width: 200px; height: 200px; line-height: 200px; text-align: center; border: 1px solid gray; color: red; } </style> <body> <div class="src"> <div class="dragabled"> <div class="txt" id="txt"> 全部的文字均可拖拽。 <p draggable="true">此段文字設置了屬性draggable="true"</p> </div> <div class="url" id="url"> <a href="http://weiqinl.com" target="_blank">我是url:http://weiqinl.com</a> </div> <img class="img" id="tupian1" src="img1.png" alt="圖片1" /> <img class="img" id="tupian2" src="img2.png" alt="圖片2" /> </div> <div id='target' class="dropabled target">Drop Here</div> </div> <script> var dragSrc = document.getElementById('txt') var target = document.getElementById('target') dragSrc.ondragstart = handle_start dragSrc.ondrag = handle_drag dragSrc.ondragend = handle_end function handle_start(e) { console.log('dragstart-在元素開始被拖動時候觸發') } function handle_drag() { console.log('drag-在元素被拖動時候反覆觸發') } function handle_end() { console.log('dragend-在拖動操做完成時觸發') } target.ondragenter = handle_enter target.ondragover = handle_over target.ondragleave = handle_leave target.ondrop = handle_drop function handle_enter(e) { console.log('handle_enter-當元素進入目的地時觸發') // 阻止瀏覽器默認行爲 e.preventDefault() } function handle_over(e) { console.log('handle_over-當元素在目的地時觸發') // 阻止瀏覽器默認行爲 e.preventDefault() } function handle_leave(e) { console.log('handle_leave-當元素離開目的地時觸發') // 阻止瀏覽器默認行爲 // e.preventDefault() } function handle_drop(e) { console.log('handle_drop-當元素在目的地放下時觸發') var t = Date.now() target.innerHTML = '' target.append(t + '-拖放觸發的事件。') e.preventDefault() } </script> </body> </html>
在整個拖放過程當中,咱們以上說的是表面現象,事件過程內部還會發生什麼事情呢?請看下面👇的DataTransfer對象。code
與拖放操做所觸發的事件同時派發的對象是DragEvent,它派生於MouseEvent,具備Event與MouseEvent對象的全部功能,並增長了dataTransfer屬性。該屬性用於保存拖放的數據和交互信息,返回DataTransfer對象。
// DataTransfer dataTransfer = DragEvent.dataTransfer
DataTransfer對象定義的屬性和方法有不少種,咱們看下列入標準的幾個。
屬性 | 說明 |
---|---|
types | 只讀屬性。它返回一個咱們在dragstart事件中設置的拖動數據格式的數組。 格式順序與拖動操做中包含的數據順序相同。IE10+、Edge、safari3.一、Firefox3.5+ 和Chrome4以上支持該屬性 |
files | 返回拖動操做中的文件列表。包含一個在數據傳輸上全部可用的本地文件列表。若是拖動操做不涉及拖動文件,此屬性是一個空列表。 |
dropEffect | 獲取當前選定的拖放操做的類型或將操做設置爲新類型。它應該始終設置成effectAllowed的可能值之一【none、move、copy、link】。dragover事件處理程序中針對放置目標來設置dropEffect。 |
effectAllowed | 指定拖放操做所容許的效果。必須是其中之一【 none, copy, copyLink, copyMove, link, linkMove, move, all, uninitialized】默認爲uninitialized 表示容許全部的效果。ondragstart處理程序中設置effectAllowed屬性 |
方法 | 說明 |
---|---|
void setData(format, data) | 將拖動操做的拖動數據設置爲指定的數據和類型。format能夠是MIME類型 |
String getData(format) | 返回指定格式的數據,format與setData()中一致 |
void clearData([format]) | 刪除給定類型的拖動操做的數據。若是給定類型的數據不存在,此方法不執行任何操做。若是不給定參數,則刪除全部類型的數據。 |
void setDragImage(img, xOffset, yOffset) | 指定一副圖像,當拖動發生時,顯示在光標下方。大多數狀況下不用設置,由於被拖動的節點被建立成默認圖片。x,y參數分別指示圖像的水平、垂直偏移量 |
//IE10及以前版本,不支持擴展的MIME類型名 //Firefox 5版本以前,不能正確的將url和text映射爲text/uri-list 和text/plain var dataTransfer = event.dataTransfer; //讀取文本, var text = dataTransfer.getData("Text"); //讀取URL, var url = dataTransfer.getData("url") || dataTransfer.getData("text/uri-list");
說了這麼多,若是瀏覽器不支持,也是白扯。
Method of easily dragging and dropping elements on a page, requiring minimal JavaScript.
要求最少的js,實現拖拽頁面元素的簡單方法
drag之瀏覽器支持程度--caniuse

note
dataTransfer.items
只有Chrome支持dropzone
屬性,目前沒有瀏覽器支持.setDragImage
任何類型的DOM元素。Chrome必須有HTMLImageElement
或者任何DOM元素,該DOM元素附加到DOM 和瀏覽器的.setDragImage
視口(viewport)內。dataTransfer.files
或者 .types
對象.setDragImage
dataTransfer.setData / getData
的有限支持格式如下,我在實際中遇到的狀況,各瀏覽器對標準的實現仍是有差別的。
getData()
在chrome 62.0瀏覽器中,只能在drop
事件中生效。setDragImage
方法,指定的圖像不存在,則拖動過程:
dragstart
和dragend
事件。dataTransfer.getData()
獲得的內容。drop
事件中,添加: e.stopPropagation();// 再也不派發事件。解決Firefox瀏覽器,打開新窗口的問題
。draggable
屬性設置爲true
,才能夠拖動。dropEffect
和 effectAllowed
。
effectAllowed
容許拖放操做的效果,最多不會超過那麼幾種。dropEffect
設置拖放操做的具體效果,只能是四種可能之一。effectAllowed
設置爲none
,則不容許拖放元素。可是各個瀏覽器能觸發的事件不同。(注意:safari能夠拖放元素,並且會觸發全部事件)dropEffect
設置爲none
,則不容許被拖放到目的地元素中。effectAllowed
的值,那麼若是要設置dropEffect
的值,其值必須和effectAllowed
的值一致,不然拖動效果無效,並且不容許將被拖放元素放到目的地元素中。(注:safari11.0.1有效果,並且也能拖動到目的地元素中,可是這不符合標準)。drag-drop-dataTransfer各屬性方法示例
drag-drop事件觸發
原生HTML5拖拽API,drag && drop 在實際工做中,仍是有不少狀況下會遇到的。 以上,我只介紹了部分經常使用API。API不復雜,多看會兒,實踐就知道了。各個瀏覽器,可能會在表現上,稍有不一樣,但我相信你們仍是會向着標準發展的。