HTML5拖放API Drag and Drop

此文研究Web API中的拖放接口,提供各個屬性和方法的說明,解決拖放過程當中的拖拽數據對象存儲和獲取問題。html

拖放API做用到兩個目標對象,分別是拖拽目標對象和放置目標對象。segmentfault

拖拽目標

一個設置draggable屬性的值爲trueDOM元素或者一個選中狀態的文本區塊能夠成爲拖拽目標。數組

<div draggable="true"></div>

OR
yy 20170629201338app

放置目標

一個綁定了下圖放置目標對應的5個事件的DOM元素能夠成爲放置目標。函數

事件

拖放API有8個事件,其中有3個事件綁定在拖拽目標上,有5個事件綁定在放置目標上。spa

綁定在拖拽目標

Evnet Description
dragstart 當用戶開始拖拽一個元素或者一個文本選取區塊的時觸發。
drag 當用戶正在拖拽一個元素或者一個文本選取區塊的時觸發。
dragend 當用戶結束拖拽一個元素或者一個文本選取區塊的時觸發。(如放開鼠標按鍵或按下鍵盤的 escap 鍵)

綁定在放置目標

Event Description
dragenter 當一個元素或文字選取區塊被拖曳移動進入一個有效的放置目標時觸發。
dragover 當一個元素或文字選取區塊被拖曳移動通過一個有效的放置目標時觸發。
dragleave 當一個元素或文字選取區塊被拖曳移動離開一個有效的放置目標時觸發。
dragexist 當一個元素再也不是被選取中的拖曳元素時觸發。(Firefox能觸發,觸發順序:dragexist->dragleave->drop;Chrome沒法觸發)
drop 當一個元素或文字選取區塊被放置至一個有效的放置目標時觸發。

經過下圖能更直觀觀察每一個事件觸發的時機.net

dragdrop-events

戳我看源碼3d

注意:在dragover事件中使用event.preventDefault();阻止默認事件,才能觸發drop事件code

DataTransfer對象

在進行拖放操做時,會觸發上面所述的8個事件,每一個event事件對象中都會有DataTransfer對象用來保存被拖動的數據。它能夠保存一項或多項數據、一種或者多種數據類型。htm

effectAllowed

用來指定拖動時被容許的效果。

dragstart事件中設置

屬性

dropEffect

設置實際的放置效果,它應該始終設置成effectAllowed的可能值之一 。

dragenter事件和dragover事件中設置

effectAllowed和dropEffect屬性的栗子:戳我看源碼

files

包含一個在數據傳輸上全部可用的本地文件列表。若是拖動操做不涉及拖動文件,此屬性是一個空列表。

filesZoneEl.addEventListener("drop", (event) => {
    event.preventDefault();
    let files = event.dataTransfer.files;
    for (let i = 0, len = files.length; i < len; i++) {
        let liEl = document.createElement("li");
        liEl.innerHTML = files[i].name;
        filesListEl.appendChild(liEl);
    }
});

drag-file

戳我看源碼

types

保存一個被存儲數據的類型列表做爲第一項,順序與被添加數據的順序一致。若是沒有添加數據將返回一個空列表。

items

存儲DataTransferItem數據對象的列表。

方法

addElement()

設置拖動源。

event.dataTransfer.addElement(element);

setData()

爲一個給定的類型設置數據並存儲在items屬性中。

getData()

items屬性中獲取給定類型的數據,無數據時返回空字符串。

event.dataTransfer.getData(type);

clearData()

items屬性中刪除與給定類型關聯的數據,若類型爲空則刪除全部數據。

event.dataTransfer.clearData(type);

setDragImage()

自定義一個指望的拖動時的圖片,默認爲被拖動的節點。

event.dataTransfer.setDragImage(imgElement, offsetX, offsetY);
Param Description
imgElement 要用做拖動反饋圖像元素。
offsetX 圖像內的水平偏移量。
offsetY 圖像內的垂直偏移量。

設置拖動時的圖片時,要把圖片預加載,不然圖片會在拖動開始dragstart事件觸發時纔會加載圖片,會致使拖動圖出不來或閃一下的後果。可把圖片放到<img>標籤並設置display:none;,原理詳看我以前的文章Web圖片資源的加載與渲染時機

drag-imgage

DataTransferItemList

dataTramsfer對象的items屬性,包含了一系列DataTransferItem拖拽數據對象。

屬性

length

數組長度。

方法

add()

增長一個拖拽數據對象到items屬性中,並返回增長的拖拽數據對象。

event.dataTransfer.items.add(file);

remove()

items屬性中移除指定位置的一個拖拽數據對象。

event.dataTransfer.items.remove(index);

clear()

清空items屬性中的所拖拽數據對象。

event.dataTransfer.items.clear();

DataTransferItem

DataTransferItemList列表中的拖拽數據對象。

屬性

kind

拖拽數據對象類型。

Value Description
file 文件類型。
string 文本字符串類型。

type

MIME類型的Unicode字符串,例如text/plaintext/htmlimage/png

方法

getAsFile()

若拖拽數據對象是文件類型,則返回一個文件對象。

let itemList = event.dataTransfer.items;
for (let i = 0, len = itemList.length; i < len; i++) {
    if (itemList[i].kind == "file") {
        console.log(itemList[i].getAsFile());
    }
}

getAsString()

若拖拽數據對象是文本字符串類型,經過回調函數獲取拖拽數據中的字符串數據。

let itemList = event.dataTransfer.items;
for (let i = 0, len = itemList.length; i < len; i++) {
    if (itemList[i].kind == "string") {
        itemList[i].getAsString((data) => {
            console.log(data);
        });
    }
}

拖放對象的數據存儲

在進行拖放操做時,有可能須要把拖拽目標的數據傳送給放置目標,此時通常操做是在dragstart事件觸發時把須要的數據存儲到一個變量,而後再drop事件觸發時獲取這個變量。但當dragstart事件和drop事件在不一樣的文件定義,又不想玷污全局變量的狀況下,咱們須要更好的辦法來存儲拖放數據。

DataTransfer對象中的items屬性就是用來存儲拖放數據的,數據類型分爲文本類型和文件類型。

存儲文本字符串類型數據:

event.dataTransfer.setData(type, data);

OR

event.dataTransfer.items.add(data, type);

一種文本字符串類型只能存儲一個數據,當重複文本字符串類型存儲數據時,後者會覆蓋前者。

存儲文件類型數據:

event.dataTransfer.items.add(file);

獲取全部文本字符串類型的拖拽數據對象

event.dataTransfer.types

獲取全部文件類型的拖拽數據對象

let files = event.dataTransfer.files;
for (let i = 0, len = files.length; i < len; i++) {
    console.log(files[i]);
}

OR

let itemList = event.dataTransfer.items;
for (let i = 0, len = itemList.length; i < len; i++) {
    if (itemList[i].kind == "file") {
        console.log(itemList[i].getAsFile());
    }
}

獲取全部文本字符串類型的拖拽數據對象

let itemList = event.dataTransfer.items;
for (let i = 0, len = itemList.length; i < len; i++) {
    if (itemList[i].kind == "string") {
        itemList[i].getAsString((data) => {
            console.log(data);
        });
    }
}

獲取指定文本字符串類型的拖拽數據對象

event.dataTransfer.getData(type);

刪除指定文本字符串類型的拖拽數據對象

event.dataTransfer.clearData(type);

刪除指定位置的拖拽數據對象

event.dataTransfer.items.remove(index);

清空全部拖拽數據對象

event.dataTransfer.clearData();

OR

event.dataTransfer.items.clear();

栗子

上面的幾個栗子都使用了以上方法存儲和獲取拖拽數據對象,感興趣的能夠看看源碼。

歡迎關注:Leechikit
原文連接:segmentfault.com

到此本文結束,歡迎提問和指正。寫原創文章不易,若本文對你有幫助,請點贊、推薦和關注做者支持。

相關文章
相關標籤/搜索