結束了精彩的 Canvas API 系列,接下來要帶大家探索更多有趣又實用的 Web API!🎉
首先登場的是 HTML5 的 Drag and Drop API 拖曳功能。
在前幾天的 Canvas 範例裡,我們其實也有透過滑鼠事件手動實作過「拖曳」效果。那種做法比較接近「遊戲式」的互動,需要完全掌控座標與繪製過程。
而今天要介紹的 Drag and Drop API,則是瀏覽器專為 DOM 元素 提供的原生機制,用起來更直覺,特別適合應用在檔案上傳、拖曳排序、或各種 UI 元素的互動操作。
過去多半用手動監聽滑鼠事件來實現拖曳,雖然彈性高,但也容易踩到各種坑。現在有了原生的 Drag and Drop API,可以讓這些互動變得更簡單、標準化。
Drag and Drop API 的核心觀念是:把元素設為可拖曳,並透過一系列事件完成「拖 → 放」的流程。
draggable
屬性只要在元素上加上 draggable="true"
,它就能成為可拖曳的物件。
<div draggable="true">拖曳我</div>
在網頁中,拖曳操作主要分為兩部分:被拖曳元素與放置目標,各自會觸發不同事件。
dragstart
:拖曳開始時觸發,可設定要傳遞的資料。drag
:拖曳過程中持續觸發。dragend
:拖曳結束時觸發(不論是否成功放在放置目標)。dragenter
:拖曳物件進入目標區域時觸發。dragover
:拖曳物件停留在目標上時持續觸發,要在這裡 event.preventDefault()
才能允許放置。dragleave
:拖曳物件離開目標區域時觸發。drop
:物件放下時觸發,可在這裡取出資料。事件流程示意圖:
被拖曳元素:
[dragstart] → [drag] → [dragend]
放置目標:
[dragenter] → [dragover] → [drop]
↘ [dragleave]
dataTransfer
物件event.dataTransfer
是拖曳過程的關鍵,用來傳遞資料。
setData(type, data)
:在 dragstart
設定要傳遞的資料。getData(type)
:在 drop
取回資料。dataTransfer.files
讀取使用者拖曳進來的檔案。理解了基本概念後,我們來看一個最簡單的範例:把一個方塊拖曳到指定區域。
HTML
<div class="drag-source" draggable="true">拖曳我</div>
<div class="drop-target">放到這裡</div>
CSS
.drag-source {
width: 100px;
height: 100px;
background: #5aa9e6;
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: grab;
}
.drop-target {
width: 200px;
height: 200px;
border: 2px dashed #aaa;
margin-top: 20px;
display: flex;
align-items: center;
justify-content: center;
color: #555;
}
JavaScript
const dragSource = document.querySelector(".drag-source");
const dropTarget = document.querySelector(".drop-target");
// 拖曳開始時,設定傳遞的資料
dragSource.addEventListener("dragstart", (e) => {
e.dataTransfer.setData("text/plain", "Hello Drag and Drop!");
});
// 允許放置
// 注意:沒有 preventDefault(),drop 事件不會觸發
dropTarget.addEventListener("dragover", (e) => {
e.preventDefault();
});
// 放下物件時,取出資料
dropTarget.addEventListener("drop", (e) => {
e.preventDefault();
const data = e.dataTransfer.getData("text/plain");
dropTarget.textContent = `接收到資料:${data}`;
});
dragstart
事件會把資料放進 dataTransfer
。drop
事件讀取資料並更新目標區塊內容。雖然我們最常在 drop
事件裡讀取資料,但其實在 同一頁元素的拖曳 裡,你也能在 dragenter
或 dragover
時就呼叫 getData("text/plain")
,提前拿到 dragstart
設定的值,用來做即時提示。
不過若是 跨應用拖曳(例如把桌面檔案拖進網頁),在 dragenter
/ dragover
階段通常只會提供檔案的「metadata」(例如檔名、型別),而真正的檔案內容則必須等到 drop
事件才會暴露。
這是瀏覽器刻意的安全設計,避免惡意網站只要你「拖曳經過」頁面,就偷取電腦裡檔案的內容。
上面我們用簡單程式碼展示了最基本的拖曳流程。
如果想直接體驗完整的互動效果,可以參考這個線上範例(同時也是本文截圖的來源):
👉 歡迎追蹤這個系列,我會從 Canvas 開始,一步步帶你認識更多 Web API 🎯