這篇文章說明拖曳功能的基本概念。
建立可拖曳的內容
在大部分瀏覽器中,文字選取、圖片和連結皆預設可以拖曳。 舉例來說,如果您將連結拖曳到網頁上,就會看到一個 你可以將標題和網址放在網址列或桌面上 捷徑或點選連結。如要將其他類型的內容設為可拖曳, 都必須使用 HTML5 拖曳 API
如要將物件設為可拖曳,請在該元素上設定 draggable=true
。大約在
任何項目都可以支援拖曳功能,包括圖片、檔案、連結、檔案或任何
標記。
以下範例建立介面來重新排列
設計成品資料欄的基本標記如下所示,如下所示:
分別將 draggable
屬性設為 true
:
<div class="container">
<div draggable="true" class="box">A</div>
<div draggable="true" class="box">B</div>
<div draggable="true" class="box">C</div>
</div>
以下是容器和方塊元素的 CSS。唯一與該 CSS 供應商
拖曳功能是cursor: move
資源。程式碼的其餘部分可控制容器的版面配置和樣式
和 Box 元素
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 10px;
}
.box {
border: 3px solid #666;
background-color: #ddd;
border-radius: .5em;
padding: 10px;
cursor: move;
}
您可以拖曳項目,但不會執行其他動作。新增 您必須採用 JavaScript API
監聽拖曳事件
如要監控拖曳程序,您可以監聽下列任一事件:
如要處理拖曳流程,您需要某種來源元素 (拖曳 資料酬載 (拖曳的項目) 和目標 ( 防止掉落)。來源元素幾乎可以是任何類型的元素。 「目標」是可接受使用者資料的放置區域或一組捨棄區域 試圖丟棄。並非所有元素都能做為目標目標。舉例來說,您無法指定 可以是圖片
開始及結束拖曳序列
為內容定義 draggable="true"
屬性後,
dragstart
事件處理常式,啟動各欄的拖曳順序。
這段程式碼會在使用者開始拖曳資料欄時,將資料欄的透明度設為 40%。 然後在拖曳事件結束時將間隔回到 100%
function handleDragStart(e) {
this.style.opacity = '0.4';
}
function handleDragEnd(e) {
this.style.opacity = '1';
}
let items = document.querySelectorAll('.container .box');
items.forEach(function (item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragend', handleDragEnd);
});
您可以前往下方的 Glitch 示範頁面查看結果。拖曳項目和其項目
不透明度變更。來源元素具有 dragstart
事件,因此設定
this.style.opacity
設為 40% 時,能為使用者提供該元素具有的視覺回饋
正在移動目前選取的項目放置項目時,來源元素
就會傳回 100% 的不透明度。
新增其他視覺提示
如要協助使用者瞭解如何與您的介面互動,請使用
dragenter
、dragover
和 dragleave
事件處理常式。在這個範例中,
除了可以拖曳之外,放置目標也是放置目標。協助使用者:
只要將拖曳項目移到某個位置上,
。舉例來說,在 CSS 中,您可以建立 over
類別
放置目標的元素:
.box.over {
border: 3px dotted #666;
}
接著,請在 JavaScript 中設定事件處理常式,並在發生以下情況時新增 over
類別:
拖曳該欄,並在拖曳的元素離開時移除。於
我們也會確實移除 dragend
處理常式的結尾類別
拖曳
document.addEventListener('DOMContentLoaded', (event) => {
function handleDragStart(e) {
this.style.opacity = '0.4';
}
function handleDragEnd(e) {
this.style.opacity = '1';
items.forEach(function (item) {
item.classList.remove('over');
});
}
function handleDragOver(e) {
e.preventDefault();
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
}
let items = document.querySelectorAll('.container .box');
items.forEach(function(item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragover', handleDragOver);
item.addEventListener('dragenter', handleDragEnter);
item.addEventListener('dragleave', handleDragLeave);
item.addEventListener('dragend', handleDragEnd);
item.addEventListener('drop', handleDrop);
});
});
在這個程式碼中,有幾個要點可以說明:
預設動作
dragover
事件的dataTransfer.dropEffect
屬性是設為"none"
。本頁稍後會介紹dropEffect
屬性。目前, 只需要知道這會導致無法觸發drop
事件。如要覆寫這項設定 行為並呼叫e.preventDefault()
。另一個建議做法false
。dragenter
事件處理常式的用途是切換over
類別,而非dragover
。如果使用dragover
,事件會在使用者同時重複觸發 將拖曳的項目保留在資料欄中,讓 CSS 類別切換 重複執行。這樣瀏覽器就會執行許多不必要的轉譯工作 而會影響使用者體驗強烈建議您盡可能減少 重新繪製。如需使用dragover
,請考慮 節流或取消彈跳事件監聽器。
開賽
如要處理放置作業,請為 drop
事件新增事件監聽器。在「drop
」中
處理常式,您需要防止瀏覽器預設的 ANR 行為;
通常是惱人的重新導向方法是呼叫 e.stopPropagation()
。
function handleDrop(e) {
e.stopPropagation(); // stops the browser from redirecting.
return false;
}
請務必註冊新的處理常式與其他處理常式:
let items = document.querySelectorAll('.container .box');
items.forEach(function(item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragover', handleDragOver);
item.addEventListener('dragenter', handleDragEnter);
item.addEventListener('dragleave', handleDragLeave);
item.addEventListener('dragend', handleDragEnd);
item.addEventListener('drop', handleDrop);
});
如果您現在執行程式碼,項目不會拖放至新的位置。目的地:
要啟動函式,請使用 DataTransfer
物件。
dataTransfer
屬性會保留透過拖曳動作傳送的資料。dataTransfer
是在 dragstart
事件中設定,並在放置事件中讀取或處理。撥號中
e.dataTransfer.setData(mimeType, dataPayload)
可讓您設定物件的 MIME
類型和資料酬載
在本例中,我們將讓使用者重新排列資料欄的順序。 要這麼做,您必須先在拖曳時儲存來源元素的 HTML 開始:
function handleDragStart(e) {
this.style.opacity = '0.4';
dragSrcEl = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', this.innerHTML);
}
在 drop
事件中,您會設定來源資料欄的
將 HTML 改成您已放置資料的目標資料欄的 HTML。這個
包含確認使用者不會回訪同一欄
function handleDrop(e) {
e.stopPropagation();
if (dragSrcEl !== this) {
dragSrcEl.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text/html');
}
return false;
}
您可以在下方示範中查看結果。如要這麼做,你必須 電腦版瀏覽器。行動裝置不支援 Drag and Drop API。拖曳 變更 B 欄上方的 A 欄,您會發現它們的變化位置:
更多拖曳屬性
dataTransfer
物件會公開屬性,為
會在拖曳過程中控制每個放置目標回應方式
特定資料類型
dataTransfer.effectAllowed
敬上 限制拖曳方式使用者可對元素執行哪些操作用途 並在拖曳處理模型中初始化dropEffect
dragenter
和dragover
事件。屬性中可有 下列值:none
、copy
、copyLink
、copyMove
、link
、linkMove
、move
、all
和uninitialized
。dataTransfer.dropEffect
敬上 控制使用者在dragenter
和dragover
期間收到的意見回饋 事件。當使用者將遊標懸停在目標元素上時,瀏覽器的 遊標指出即將進行的作業類型,例如副本 或是進行特定動作效果可能為下列其中一個值:none
、copy
、link
、move
。e.dataTransfer.setDragImage(imgElement, x, y)
敬上 意味著不用使用瀏覽器的預設「ghost 圖片」提供意見,您 可以設定拖曳圖示
上傳檔案
這個簡易範例使用資料欄做為拖曳來源和拖曳目標。這個 會發生於 UI 要求使用者重新排列項目在某些情況下 拖曳目標和來源可能會有不同的元素類型,就像在介面中一樣 使用者必須選取一張圖片做為產品的主要圖片, 將所選圖片拖曳到目標上
使用者經常以拖曳方式將桌面項目拖曳到
負載平衡器的工作就是將使用者流量
平均分配給應用程式的多個執行個體主要差異在於 drop
處理常式。不使用
「dataTransfer.getData()
」用於存取檔案,其資料包含在以下位置:
dataTransfer.files
屬性:
function handleDrop(e) {
e.stopPropagation(); // Stops some browsers from redirecting.
e.preventDefault();
var files = e.dataTransfer.files;
for (var i = 0, f; (f = files[i]); i++) {
// Read the File objects in this FileList.
}
}
想進一步瞭解這項功能,請前往 自訂拖曳。