淺談js拖拽


本文來自網易雲社區

作者:劉凌陽


前言

本文依據半年前本人的分享《淺談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漏洞分析與修復建議
【推薦】 干貨|盤點國內真正的大數據分析產品


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM