1. 程式人生 > 其它 >HTML5拖拽技術介紹

HTML5拖拽技術介紹

HTML5 的拖拽實現

前提:draggable

將需要拖放的元素設定為 draggable = 'true'(img 和 a 元素預設為 true)

一、拖放相關事件

1. 被拖動元素: ondragstart、ondrag、ondragend

  • ondragstart :使用者開始拖動元素時觸發
  • ondrag :元素正在拖動時觸發
  • ondragend :使用者完成元素拖動後觸發

2. 放置目標元素(容器): ondragenter、ondragover、ondragleave、ondrop

  • dragenter :當被滑鼠拖動的物件進入其容器範圍內時觸發此事件
  • dragover :當某被拖動的物件在另一物件容器範圍內拖動時觸發此事件
  • dragleave :當被滑鼠拖動的物件離開其容器範圍內時觸發此事件
  • drop :在一個拖動過程中,釋放滑鼠鍵時觸發此事件。
    • 源物件拖放到目標物件中,目標物件完全接受被拖拽物件時觸發,可理解為在目標物件內鬆手時觸發

注意:對於 dragover drop,預設地,資料/元素無法被放置到其他元素中。為了實現拖放,我們必須阻止元素的這種預設的處理方式: 呼叫 event.preventDefault();

二、資料的傳遞:dataTransfer

所有拖放事件的引數 DragEvent中,都提供了一個數據傳輸物件: dataTransfer,用於在源物件和目標物件之間傳遞資料。

DataTransfer

物件包含了拖拽事件的狀態,例如拖拽事件的型別(如拷貝 copy 或者移動 move),拖拽的資料(一個或者多個項)和每個拖拽項的型別(MIME 型別)。 DataTransfer 物件也有向拖拽資料中新增或刪除專案的方法。

參考連結:MDN : DataTransfer

1. dataTransfer的方法

setData(format, data)

該方法設定拖拽事件中要傳遞的資料,向 dataTransfer 中物件中存入資料。

接受兩個引數:

format:DOMString,表示要新增到 drag object的拖動資料的型別。例如text/plain、text/html、text/xml、text/uri-list

data

:DOMString,表示要新增到 drag object的資料。例如event.dataTransfer.setData('text/plain', 'hello world')

注:如果給定型別的資料不存在,則將其新增到拖動資料儲存的末尾,使得 dataTransfer.types 列表中的最後一個專案將是新型別。

getData(format)

該方法獲得拖拽事件中傳遞的資料,從 dataTransfer 物件中讀取資料

引數 format 為在 setData 方法中指定的資料型別,例如: event.dataTransfer.getData('text/plain')

clearData()

該方法清空 dataTransfer 物件中儲存的資料,引數可選,為資料型別。若為空,則清空所有資料。

setDragImage(element, x, y)

該方法通過 img 元素來設定拖放圖示

element 表示拖拽時滑鼠下面的圖片(通常是 image 元素,也可以說 canvas 元素)

xy分別指示相對於圖片的橫向和縱向偏移量,相對應滑鼠指標。

2. dataTransfer的屬性

files 屬性

返回被拖拽的檔案列表,是一個 FileList 物件,有 length 屬性,可通過下標訪問。

如果拖動操作不涉及拖動檔案,則此屬性為空列表.

dropEffect 屬性

獲取當前選定的拖放操作型別或者設定的為一個新的型別。值必須為 none, copy, link 或 move

必須在 dragenter 事件處理函式中設定。

  • none 不能把元素拖放至此(除文字框外全部元素的預設值)
  • move 移動到目標
  • copy 複製到目標
  • link 目標開啟拖動元素(拖動元素必須是連結並有 URL)

dropEffect 屬性

提供所有可用的操作型別。必須是 none, copy, copyLink, copyMove, link, linkMove, move, all or uninitialized 之一。

必須在 dragstart 事件處理函式中設定。

  • uninitialized 沒有設定任何拖放行為
  • none 不能由任何行為
  • copy 僅允許 dropEffect 值為 copy
  • link 僅允許 dropEffect 值為 link
  • move 僅允許 dropEffect 值為 move
  • copyLink 允許 dropEffect 值為 copy 和 link
  • copyMove 允許 dropEffect 值為 copy 和 move
  • linkMove 允許 dropEffect 值為 link 和 move
  • all 允許任意 dropEffect

三、示例:HTML 拖拽示例 drag & drop

HTML 程式碼

<div class="drag-item" id="dragitem" draggable="true">被拖動元素</div>

<div class="target-area">
  <div class="target" id="t1">目標元素</div>
  <div class="target" id="t2">目標元素2</div>
</div>

<div class="status-area">
  <div id="info">請拖動</div>
  <div id="info2"></div>
</div>

JavaScript 程式碼

let item = document.getElementById('dragitem')
let info = document.getElementById('info')
let info2 = document.getElementById('info2')
let targets = document.getElementsByClassName('target')

item.addEventListener('dragstart', function(ev){
  ev.target.style.background = "lightgreen";
  ev.target.style.color = "black";
  ev.target.style.opacity = 0.5;
  info.innerHTML = "開始拖動";

  // 設定傳遞資料
  ev.dataTransfer.setData('itemid', ev.target.id)
})

item.addEventListener('dragend', function(ev){
  ev.target.style.background = "black";
  ev.target.style.color = "white";
  info.innerHTML = "結束拖動";
  ev.target.style.opacity = 1;
  info2.innerHTML = "";
})

item.addEventListener('drag', function(ev){
  info2.innerHTML = "拖動中";
})

for(let target of targets) {

  target.addEventListener('dragover', function(ev) {
    //預設地,資料/元素無法被放置到其他元素中。
    //為了實現拖放,我們必須阻止元素的這種預設的處理方式
    ev.preventDefault();
  })

  target.addEventListener('dragenter', function(ev) {
    ev.target.style.border = "3px dotted red";
  })

  target.addEventListener('dragleave', function(ev) {
    ev.target.style.border = "1px solid black";
  })

  target.addEventListener('drop', function(ev) {
    ev.preventDefault();
    let id = ev.dataTransfer.getData('itemid')
    ev.target.appendChild(document.getElementById(id))
  })

  target.addEventListener('dragover', function(ev) {
    ev.preventDefault();
    ev.target.style.border = "3px dotted red";
  })
}