HTML5 Drag和Drop 拖拽

admin發表於2019-03-05

HTML5之前,實現拖拽功能比較複雜,通常利用mousemove或者mousedown等事件完成。

上述方式操作非常不便,有各種坑去填,HTML5的出現使拖拽操作變得更加簡單,下面進行一下詳細介紹。

一.IE並非一無是處:

作為前端人員,一直都不喜歡IE瀏覽器,有此感受的同仁應該不在少數。

但是拖拽功能的確最早由IE瀏覽器實現,並且版本非常早(IE4),當然功能沒有現在的如此完善。

後來,HTML5在IE的拖拽基礎上進行了規範化,擴充套件了很多功能,於是有了本章節將要介紹的知識點。

二.HTML5拖放實現原理簡述:

拖拽實現的原理非常簡單,下面進行一下簡述,再後面會有詳細的介紹:

(1).拖拽並不是一個元素的事情,而是被拖拽元素與目的地元素互動完成。

(2).在拖拽過程中通過監聽被拖拽元素與目的地元素相關事件以此執行相關的操作。

(3).拖拽過程中的相關資料是通過事件物件的dataTransfer屬性完成。

下面分步對拖拽操作進行一下詳細介紹。

三.拖拽操作相關元素:

拖拽操作不是一個元素的事情,而是被拖拽元素與目的地元素互動完成。

也就是整個過程是將一個元素通過拖拽操作放置於另一個元素之上。

通過監聽這兩個元素與拖拽相關的事件可以實現對拖拽細節的控制,下面會介紹。

四.拖拽操作事件:

被拖拽元素與目的地元素上的事件是不同的分別如下:

1.被拖拽元素事件:

(1).dragstart:開始拖拽時觸發此事件。

(2).drag:dragstart事件觸發後,隨後觸發,元素被拖動期間此事件會持續觸發,類似mousemove事件。

(3).dragend:當放開被拖拽元素也就是拖拽結束後觸發該事件。

2.目標元素事件:

(1).dragenter::當被拖拽元素進入時觸發此事件。

(2).dragover:此事件會緊接著dragenter事件觸發,並且在拖動期間持續觸發。

(3).dragleave:當被拖拽元素離開目的地元素的時候觸發。

(4).drop:當結束拖拽時觸發此事件。

五.dataTransfer物件:

dataTransfer是事件物件的一個屬性,返回值是一個物件,權且稱之為dataTransfer物件。

前面提到過通過dataTransfer物件可以實現拖拽的資料互動。

考慮到文章的篇幅問題,文字不做更多的介紹,具體參閱JavaScript dataTransfer一章節。

六.dropEffect與effectAllowed:

這兩個屬性屬於dataTransfer物件,通過這兩個屬性可以規定被拖動元素和目的元素所允許的操作。

同樣考慮到篇幅問題,這兩個屬性可以參閱JavaScript dropEffect與effectAllowed一章節。

七.程式碼例項分析:

前面都是介紹的理論,很多細節需要通過程式碼例項來完善,也可以加深記憶。

看一個非常簡單的案例,然後對其進行分析:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!DOCTYPE html>  
<html>  
<head>  
<meta charset=" utf-8">  
<meta name="author" content="http://www.softwhy.com/" />  
<title>螞蟻部落</title>
<style>
#ant {
    width:350px;
    height:100px;
    padding:10px;
    background-color: #ccc;
}
</style>
<script>
window.onload=function(){
    let ant=document.getElementById("ant");
    let dr=document.getElementById("dr");
    
    ant.ondragover=function(ev){
      ev.preventDefault();
    }
    dr.ondragstart=function(ev){
      ev.dataTransfer.setData("Text",ev.target.id);
    }

    ant.ondrop=function(ev){
      ev.preventDefault();
            ev.stopPropagation()
      let data=ev.dataTransfer.getData("Text");
      ev.target.appendChild(document.getElementById(data));
    }
}    
</script>    
</head>
<body>
<p>按住滑鼠拖動圖片到矩形框</p>
<div id="ant"></div>
<br>
<img id="dr" src="demo/js/img/dr.png" draggable="true">
<script>
</script>
</body>
</html>

程式碼實現了簡單的拖拽效果,滑鼠按住圖片可以將其拖動到矩形框。

比較簡單,如果需要稍微複雜一點的演示可以參閱HTML5 拖拽效果程式碼例項一章節。

下面對上述效果的實現過程進行一下詳細分析:

將圖片的draggable屬性設定為true即可將其設定為可拖拽,否則元素預設是不可拖拽的。

特別說明:連結、圖片和選中的文字預設都是可以拖拽的,所以程式碼中的draggable="true"可以省略。

[JavaScript] 純文字檢視 複製程式碼
let ant=document.getElementById("ant");
let dr=document.getElementById("dr");

分別獲取拖拽目的地元素(矩形框)和被拖拽圖片。

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

上面這個程式碼很重要,很多初學者可能忽略,由此導致無法完成拖拽。

預設情況下,目標元素是不允許在其上放置其他元素,所以需要ev.preventDefault()阻止其預設動作。

關於preventDefault方法更多內容可以參閱JavaScript preventDefault()一章節。

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

為圖片註冊dragstart事件,當開始拖動的時候觸發。

然後將被拖動圖片的id屬性值存入dataTransfer物件中。

dataTransfer.setData方的具體用法本文不做介紹,簡單點說就是以指定的格式儲存資料。

關於此方法的具體用法可以參閱dataTransfer.setData()一章節。

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

為目標元素也就是div元素註冊drop事件,此事件在拖拽結束時觸發。

特別說明:只要滑鼠鬆開被拖拽元素,那麼表示拖拽操作結束,此事件就會觸發。

當拖動一個元素到目標元素,在有些瀏覽器中(火狐瀏覽器),預設在一個新的連結開啟被拖動元素,這通常是不允許的,所以上述程式碼中的如下兩行是必須的:

[JavaScript] 純文字檢視 複製程式碼
ev.preventDefault();
ev.stopPropagation();

上述兩行是必須的,否則依然可能會在新視窗開啟拖動元素,例如在火狐瀏覽器中。

最後利用dataTransfer.getData方法獲取被拖動元素的id屬性值,然後通過此id獲取被拖動元素,將其插入到目的地元素中,最終完成圖片拖動效果。

相關閱讀:

(1).appendChild方法參閱JavaScript appendChild()一章節。

(2).target屬性參閱event.relatedTarget一章節。

(3).document.getElementById參閱document.getElementById()一章節。

相關文章