本文來自網易雲社區
作者:劉凌陽
前言
本文依據半年前本人的分享《淺談js拖拽》撰寫,算是一篇遲到的文章。
基本思路
雖然現在關於拖拽的組件庫到處都是,HTML5也把拖放納入了標准。但考慮到兼容問題,我們還是從最古老的方式開始講起。
onmousedown:模擬開始拖拽事件。 鼠標按鍵按下即發生 onmousedown 事件。 獲取鼠標位置,獲取被拖拽元素的位置,記錄兩者之間的縱橫坐標的差值。對 document 元素綁定 onmousemove,onmouseup 事件。
為什么是對 document 綁定而不是對被拖動的元素綁定呢?原來是如果對被拖動元素綁定的話當鼠標拖動過快時,會導致鼠標與被拖動元素的脫離。
onmousemove:模擬拖拽中事件。 鼠標拖動即發生 onmousemove 事件。 將被拖拽元素的 position 改成絕對位置,這個可以通過 left 和 top 改變該元素的位置,從而使得該元素隨着鼠標的拖拽而移動。獲取鼠標位置,將鼠標 x 坐標( e.clientX )減去第 2 步儲存的橫坐標差作為被拖動元素的 left 值,將鼠標y 坐標( e.clientY )減去第 2 步儲存的縱坐標差作為被拖動元素的 top 值。實現元素跟隨鼠標拖動的效果。
onmouseup:模擬拖拽結束事件。 鼠標按鍵彈起即發生 onmouseup 事件。可以回收 onmousemove 和 onmousedown中的 事件和變量,一次拖拽至此結束。
( nej 也提供了拖拽的一個簡單案例,位於 util/dragger/ 下,代碼就不貼出來了,有興趣的童鞋可以自行查閱,畢竟看文字實在是過於枯燥了。 )
HTML5拖放
有古老的方式自然有潮流的方式,如果你無需考慮兼容性問題的話,筆者強烈建議你使用HTML5提供的拖放API 。如果你還未曾了解,提供你一個 簡單的HTML5拖放實例 http://www.w3school.com.cn/tiy/t.asp?f=html5_draganddrop。
讓我們一起來看看HTML5拖放相關的一些知識點。
7個事件:
dragstart :當用戶開始拖動對象時觸發。
dragenter : 當鼠標第一次經過目標元素,且有拖動發生時觸發。此事件的監聽者應指明在這個位置上是否允許 drop ,或者監聽者不執行任何操作,那么 drop 默認是不允許的。
dragover :當鼠標經過一個元素時,且有拖動發生時觸發 。
dragleave :當鼠標離開一個元素,且有拖動在發生時觸發。
drag : 當對象被拖動,每次移動鼠標時觸發。
drop :在 drag 操作的最后發生 drop 時,在元素上觸發此事件。監聽者應該負責檢索拖動的數據,並插入 drop 的位置。
dragend : 在拖動對象時放開鼠標按鍵時觸發。
draggable屬性:
如果網頁元素的draggable元素為true,這個元素就是可以拖動的。
<div draggable="true">Draggable Div</div>
dataTransfer對象:
拖動過程中,回調函數接受的事件參數,有一個dataTransfer屬性。它指向一個對象,包含了與拖動相關的各種信息。
dataTransfer對象的屬性:
dropEffect:拖放的操作類型,決定了瀏覽器如何顯示鼠標形狀,可能的值為copy、move、link和none。
effectAllowed:指定所允許的操作,可能的值為copy、move、link、copyLink、copyMove、linkMove、all、none和uninitialized(默認值,等同於all,即允許一切操作)。
files:包含一個FileList對象,表示拖放所涉及的文件,主要用於處理從文件系統拖入瀏覽器的文件。
types:儲存在DataTransfer對象的數據的類型。
dataTransfer對象的方法:
setData(format, data):在dataTransfer對象上儲存數據。第一個參數format用來指定儲存的數據類型,比如text、url、text/html等。
getData(format):從dataTransfer對象取出數據。
clearData(format):清除dataTransfer對象所儲存的數據。如果指定了format參數,則只清除該格式的數據,否則清除所有數據。
setDragImage(imgElement, x, y):指定拖動過程中顯示的圖像。默認情況下,許多瀏覽器顯示一個被拖動元素的半透明版本。參數imgElement必須是一個圖像元素,而不是指向圖像的路徑,參數x和y表示圖像相對於鼠標的位置。
dataTransfer對象, 允許在其上存儲數據,這使得在被拖動元素與目標元素之間傳送信息成為可能。
e.preventDefault():
ondragover有一個默認行為,那就是當 ondragover觸發時,ondrop會失效!
如何阻止?
ondragover = function(e){e.preventDefault(); ....}
附一張整理好的圖片供大家理解:
案例
扯了這么多,最后再舉個栗子來結束本文。先上圖片...
這是筆者在網易有數項目中的一個需求,實現文件拖拽上傳。
實現步驟:
1.監聽事件
其中dragenter和dragleave只是處理了外框高亮的效果,如上面圖片所示。
需要注意的是一定要將dragover的默認事件取消掉,不然無法觸發drop事件。可以用preventDefault(),也可以用nej的_v._$stop(_event)。如需拖拽頁面里的元素,需要給其添加屬性draggable=”true”。這些上文已經有所提及。
2.處理drop事件
在drop事件回調函數中通過_event.dataTransfer.files獲取拖拽文件列表。dataTransfer對象真是個好東西。
3.發送文件數據
使用FormData模擬表單數據AJAX提交文件流。
至此,HTML5的文件拖拽上傳就實現了,是不是很easy?
網易雲大禮包:https://www.163yun.com/gift
本文來自網易實踐者社區,經作者劉凌陽授權發布
相關文章:
【推薦】 定心丸!ZipperDown漏洞分析與修復建議
【推薦】 干貨|盤點國內真正的大數據分析產品