First touch with Drag & Drop API

Paul Li
5 min readApr 23, 2024

--

First touch with Drag & Drop API

Introduction

Drag & Drop 一直都是 web page 非常普遍的行為,為了取得最高相容性,所以多數 web developers 都會依環境差異選擇監聽 mousedown / mousemove / mouseup 或是 touchstart / touchmove / touchend 等事件,為了讓 Drag & Drop (以下簡稱 DD) 行為可以符合期待,所以常常會需要用到很多額外的處理,比方說拖曳元件以及拖曳點的 offsetX 以及 offsetY,亦要自己模擬拖曳元件隨著 cursor 座標變化做出對應的位移調整。

個人覺得這是精緻手工業,也因為這樣,每每收到 DD 相關需求總會讓筆者相當抗拒~

其實 HTML 很早之前就有制定出 Drag & Drop 相關 API ,不過由於瀏覽器開發商的自大以及解讀認知不同,所以跨瀏覽器支援就變得奇差無比,這亦是筆者遲遲未導入 Drag & Drop API 的原因。

這麼多年過去了,感覺 Safari 上道不少且恰巧手上又有一個類似的需求,所以決定再來挑戰 DD API,透過 attribute [draggable=true] 以及 drag series events 的加持,不僅輕鬆完成跨瀏覽器支援,也讓整體的 code 簡約不少,不僅在功能上符合需求,亦大大強化 code 的可獨以及維護性。

以下為透過 DD API 所做出的拖曳排序效果:

接下來會跟大家一起導讀相關的實作。

Instantiation

以下為此次用到的相關 style、HTML 以及 JavaScript code,大家可以把它們依序置入自己的 web page 中,便可以直接進行測試。

Elements for drag

要讓 drag 行為可以發生需要滿足以下兩個條件:

  • 待 drag 的元件需要掛上 attribute — “draggable=true”。
  • 待 drag 的元件需要掛上 dragstart 事件監聽。

這裡有個地方需要特別注意,就是需要在 dragstart event handler 裡頭呼叫 event.dataTransfer.setData (Row.10) 進行內容設置,如果沒有設置的話,則 Safari 便無法正常啟動 drag 行為 (又是天殺的 Safari)。

dataTransfer 亦提供一個 method — setDragImage 可以讓 developers 客製化拖曳物件。它可以是 image、canvas 或是既存頁面的元件。另外也可以透過 offsetX / offsetY 來調整相對座標 (以左上為原點)。

下圖便是使用既存頁面的 HTML element 來客製化拖曳物件:

customize dragImage

使用既存頁面的 HTML element 來作為拖曳物件時需要特別注意,由於他的實作原理是針對該元件進行 screenshot,所以也會把該元件後面的背景一起照下來,這其實蠻不符合預期!!

不過有個 workaround,就是使該元件脫離當前 viewport,這樣針對 element 進行 screenshot 的時候就不會連同其身後的背景一起照下來了,這也就是 Row.3 ~Row.5 的實質作用了。

Drop Zone

既然被拖曳元件有相關事件可以設置,那麼 drop zone 元件也有專屬的事件可以被監聽。比較有趣的是 dragover 以及 drop 這兩個事件要搭配使用才能有效間聽到 drop。此外,這兩個事件的 handler 要記得呼叫 event.prevenDefault() 以阻止瀏覽器既有行為。

Active drag behavior in mobile device

一般來說 DD 很直覺的就是拖曳移動且放下的行為,不過在 iOS 或者 Android 上卻不是這麼一回事,需要長壓約莫 1.5 秒才能正常啟動 drag 行為這也是 desktop 和 mobile 最大的差異。在進行測試的時候千萬要記得此點,不然真的會鬼擋牆到吐血~

Conclusion

以上便是 HTML Drag & Drop API 的相關使用心得,雖然說有些眉角,不過相較透過 mouse / touch series events 來說真的簡約許多。如果手上專案有類似的需求,不妨放膽啟用它吧!希望本篇分享對大家都有所助益~ #drag #drop

Reference

--

--

Paul Li

Paul is the lead programmer of the AMP project at Yahoo Taiwan and is always eager for modern web technologies. He is also focusing on UX for vivid user flow.