Drag & Drop 拖拽詳解

admin發表於2019-10-05

學習一個技術最好從例項入手,可以直接演示操作效果。

然後再對照程式碼分析每一步操作來龍去脈,本文將詳細分析一段關於拖放的程式碼。

程式碼例項如下:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset=" utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style type="text/css">
p{
  width:100px;
  height:50px;
  background-color:red;
}
#box {
  width:300px; 
  height:100px;
  background-color:#ccc;
}
</style>
<script>
window.onload=function(){
  let odiv=document.getElementById("box");
  let op=document.getElementById("p");

  op.ondragstart = (ev) => {
    ev.dataTransfer.setData("Text",ev.target.id);
  }

  odiv.ondragover = (ev) => {
    ev.preventDefault();
  }

  odiv.ondrop = (ev) => {
    ev.preventDefault();
    ev.stopPropagation();
    let data=ev.dataTransfer.getData("Text");
    ev.target.appendChild(document.getElementById(data));
  }
}
</script>
</head>
<body>
<p draggable="true" id="p"></p>
<div id="box"></div>
</body>
</html>

上述程式碼可以將紅色矩形拖放到灰色矩形中去,程式碼分析如下:

[HTML] 純文字檢視 複製程式碼
<p draggable="true" id="p"></p>

將p元素的draggable屬性值設定為true,這樣此元素就是可以拖動的。

關於設定可拖動更多內容可以參閱HTML元素設定可拖拽一章節。

[JavaScript] 純文字檢視 複製程式碼
op.ondragstart = (ev) => {
  ev.dataTransfer.setData("Text",ev.target.id);
}

被拖動元素暫且稱之為源元素,目的地元素暫且稱之為目標元素。

源元素註冊dragstart事件處理函式,此事件會在源元素被拖動時觸發。

事件物件的dataTransfer屬性用於從源元素向目標元素傳遞資料。

上述程式碼通過dataTransfer.setData()方法將源元素的id屬性值儲存起來,以便在目標元素中獲取。

具體參閱JavaScript dragstart 事件一章節。

註冊在源元素的事件:

(1).dragstart:當源元素開始拖動時觸發。

(2).drag:源元素拖動過程中持續觸發。

(3).dragend:當拖動操作的滑鼠鬆開時觸發此事件,無論是否位於目標元素內。

註冊在目標元素的事件:

(1).dragenter:當拖動操作的滑鼠指標進入目標元素時觸發。

(2).dragover:當拖動操作的滑鼠指標在目標元素內移動時觸發。

(3).dragleave:當拖動操作的滑鼠指標離開目標元素時觸發。

(4).drop:當拖動操作的滑鼠指標位於目標元素內,並鬆開滑鼠時觸發。

[JavaScript] 純文字檢視 複製程式碼
odiv.ondragover = (ev) => {
  ev.preventDefault();
}

為目標元素註冊dragover事件處理函式,當拖動源元素的滑鼠指標在目標元素上移動時觸發。

ev.preventDefault()方法非常重要,否則無法完成拖動效果。

預設,目標元素是不允許放置文件內其他元素(允許放置從作業系統拖拽的檔案)。

所以要通過ev.preventDefault()取消此預設行為。

具體參閱JavaScript dragover 事件一章節。

[JavaScript] 純文字檢視 複製程式碼
odiv.ondrop = (ev) => {
  ev.preventDefault();
  ev.stopPropagation();
  let data=ev.dataTransfer.getData("Text");
  ev.target.appendChild(document.getElementById(data));
}

當源元素被放置於目標元素之上時觸發drop事件。

預設,拖動作業系統源元素,然後放置於目標元素中,會在新的標籤開啟資源。

所以需要ev.preventDefault()方法取消此預設動作。

火狐瀏覽器中,拖動文件內源元素至目標元素,會開啟一個新標籤,並進行搜尋操作。

ev.stopPropagation()方法可以組織火狐瀏覽器的此動作,其他瀏覽器不會有此問題。

文章最後總結:

(1).前面對拖拽簡單程式碼進行了分析,以便於讀者對拖拽有一個整體把握。

(2).拖拽操作設計的內容比較多,本文並未全部涉及,可以參閱本板塊的其他文章。

相關文章