HTML Drag and Drop API

HTML 拖放 介面使應用程式能夠在瀏覽器中使用拖放功能。

使用者可以使用滑鼠選擇可拖放的元素,將這些元素拖放到可放置的元素上,然後透過釋放滑鼠按鈕來放置它們。在拖動操作過程中,可拖放元素的半透明表示會跟隨指標移動。

您可以自定義哪些元素可以成為可拖放的,可拖放元素產生的反饋型別,以及可放置的元素。

此 HTML 拖放概述包括介面描述、嚮應用程式新增拖放支援的基本步驟,以及介面的互操作性摘要。

概念與用法

從表面上看,拖放實際上有三種不同的用例:在頁面內拖動元素、將資料從頁面拖出,以及將資料拖入頁面。它們在需求和實現上都有細微的差異。然而,拖放 API 提供了一個統一的模型來思考所有這些互動。

核心而言,拖動操作涉及三件事

  • 要拖動的專案
  • 要傳輸的底層資料
  • 放置目標

並非所有這三項都一定在你的控制之下,或者需要你自己定義它們

  • 當將外部資料拖入頁面時,沒有可拖動的專案需要定義(例如,可能是作業系統檔案瀏覽器中的檔案)。
  • 當在頁面內拖動元素時,你通常不需要定義任何傳輸的資料;你只需要操作被拖動的元素。
  • 當從頁面拖出時,沒有放置目標需要定義。

我們將看看每種如何定義和使用。

拖動事件

HTML 拖放使用DOM 事件模型和從滑鼠事件繼承的拖動事件。在拖動操作期間,會觸發多個事件型別,某些事件可能會觸發多次,例如dragdragover事件。

Event 何時觸發...
dragstart ...可拖動的專案開始被拖動。
drag ...可拖動的專案正在被拖動,每隔幾百毫秒。
dragenter ...可拖動的專案進入該元素。
dragleave ...可拖動的專案離開該元素。
dragover ...可拖動的專案正在該元素上方拖動,每隔幾百毫秒。
drop ...該元素是放置目標,並且可拖動的專案被放置在該元素上。
dragend ...可拖動的專案停止被拖動。

注意: dragstartdragdragend事件在被拖動的專案上觸發,因此在從作業系統將檔案拖入瀏覽器時可能不會觸發。

同樣,dragenterdragleavedragoverdrop事件在可能成為放置目標的元素上觸發,因此在將專案從瀏覽器拖出時可能不會觸發。

有關更多資訊,請參閱拖動操作

可拖動的專案

在 HTML 中,影像、連結和選擇內容預設是可拖動的。要使任意元素可拖動,請將draggable屬性設定為"true"

html
<p id="p1" draggable="true">This element is draggable.</p>

此時,該元素已經具有拖動外觀,儘管尚未定義任何行為

對於影像和連結,draggable預設為true,因此您只需將其設定為false即可停用這些元素的拖動。對於不可拖動的元素,“拖動”手勢通常會選擇文字。

注意: 當元素被設定為可拖動時,其內部的文字或其他元素將無法透過單擊和拖動滑鼠進行正常選擇。使用者必須按住Alt鍵才能用滑鼠選擇文字,或使用鍵盤。

選擇內容也是可拖動的。在這種情況下,源節點,即觸發dragstartdragend等各種事件的節點,是拖動開始的文字節點。選擇內容可以部分或完全包含多個節點,包括文字節點和元素節點,這些節點都被視為同時被拖動。

如前所述,要拖動的專案也可以是網頁上不存在的內容——例如,作業系統檔案瀏覽器中的檔案。但是,只有網頁上的專案才能觸發dragstartdragend事件。

有關更多資訊,請參閱拖動操作指南

拖動資料儲存

您不能直接將 JavaScript 物件傳輸到任意網頁,更不用說傳輸到外部應用程式了,因此要將資料傳輸進出網頁,資料必須序列化為字串(或作為File)。在拖放中,此字串封裝在DataTransferItem物件中,該物件還定義了一個特定的type——通常是 MIME 型別,如text/html——該型別定義了字串應如何被解釋。

每個拖放操作都有一個相關的拖動資料儲存,它是一個DataTransfer物件,可以透過DragEventdataTransfer屬性訪問。對於預設可拖動的專案,如影像、連結和選擇內容,拖動資料已由瀏覽器定義;對於使用draggable屬性定義的自定義可拖動元素,您必須自己定義拖動資料。修改資料儲存的唯一時間是在dragstart處理程式中——對於任何其他拖動事件的dataTransfer,資料儲存是不可修改的。

setData()方法可用於向拖動資料新增專案,如下面的示例所示。

js
function dragstartHandler(ev) {
  // Add different types of drag data
  ev.dataTransfer.setData("text/plain", ev.target.innerText);
  ev.dataTransfer.setData("text/html", ev.target.outerHTML);
  ev.dataTransfer.setData(
    "text/uri-list",
    ev.target.ownerDocument.location.href,
  );
}

const p1 = document.getElementById("p1");
p1.addEventListener("dragstart", dragstartHandler);

此外,除了dragstart事件之外,您唯一可以讀取資料儲存的時間是在drop事件期間(允許放置目標檢索資料)。對於所有其他事件,資料儲存無法訪問。

有關更多資訊,請閱讀處理拖動資料儲存

放置目標

放置目標是使用者可以放置被拖動專案的元素。預設情況下,大多數元素都不是放置目標,如果您釋放拖動,會顯示“彈回”動畫,表示拖放失敗。任何元素都可以透過取消在其上觸發的dragover事件(使用preventDefault())來成為放置目標。

drop事件僅在放置目標上觸發,並且是您可以讀取拖動資料儲存的唯一時間。

以下示例顯示了一個最小有效放置目標,並結合了先前示例中的程式碼。

html
<p id="target">Drop Zone</p>
js
const target = document.getElementById("target");

// Cancel dragover so that drop can fire
target.addEventListener("dragover", (ev) => {
  ev.preventDefault();
});
target.addEventListener("drop", (ev) => {
  ev.preventDefault();
  const data = ev.dataTransfer.getData("text/plain");
  ev.target.append(data);
});

有關更多資訊,請參閱指定放置目標

指南

拖放操作

描述了拖放操作期間發生的步驟,以及應用程式在每個處理程式中應該做什麼。

處理拖動資料儲存

描述了在拖放操作期間如何讀寫拖動資料儲存。

檔案拖放

一個實現接受檔案拖放的基本介面的實踐指南。

帶有拖放功能的看板

一個實現涉及在網頁內拖放元素的看板的實踐指南。

介面

DragEvent

傳遞給拖動事件處理程式的事件物件。

DataTransfer

包含在上下文之間傳輸的任何資料,由文字項和檔案項組成。最初為拖放設計,現在也用於其他上下文,如剪貼簿 API

DataTransferItem

表示拖動資料儲存中的一項,可以是文字項或檔案項。

DataTransferItemList

表示拖動資料儲存中DataTransferItem物件的列表。

示例

每個介面的參考頁面也有單獨的示例。

規範

規範
HTML

另見