1. 程式人生 > >深入理解原生js拖放(draggable)

深入理解原生js拖放(draggable)

本來是打算要自己總結的,但發現了一篇比較好的部落格,把我想寫的都寫了,甚至更加全面,所以,我只把我認為比較重要的知識點提煉一下,其他的都是轉載的,想看原博主的請點選原生js拖放

提煉知識點:

.draggable:設定為true,元素就可以拖拽了

拖拽元素事件:事件物件為被拖拽元素

  • ——dragstart,拖拽前觸發
  • ——drag,拖拽前、拖拽結束之間,連續觸發
  • ——dragend,拖拽結束觸發

目標元素事件:事件物件為目標元素

  • ——dragenter,進入目標元素觸發,相當於mouseover
  • ——dragover,進入目標、離開目標之間,連續觸發
  • ——dragleave,離開目標元素觸發,,相當於mouseout
  • ——drop,在目標元素上釋放滑鼠觸發

事件的執行順序:drop不觸發的時候

  • dragstart>drag>dragenter>dragover>dragleave>dragend

事件執行順序:drop觸發的時候

  • dragstart>drag>dragenter>dragover>drop>dragend

不能釋放的游標和能釋放的游標不一樣

解決火狐下的問題——必須設定dataTransfer物件才可以拖拽除圖片外的其他標籤

dataTransfer物件:

  • ——setDate():設定資料key和value(必須是字串)
  • ——getDate():獲取資料,根據key值,獲取對應的value
  • ——effectAllowed:設定游標樣式(none,copy,copyLink,copyMove,link,linkMove,move,all,uninitialized)
  • ——setDragimage(三個引數:指定的元素,座標X,座標Y)

——files:獲取外部拖拽的檔案,返回一個filesList列表,fileList下有個type屬性,返回檔案的型別//這些博主的文章中並沒有提及,我會在後續的文章中提到。)

FileReader(讀取檔案資訊)

——readAsDataURL(引數為要讀取的檔案物件,將檔案讀取為DataUrl)

——onload(當讀取檔案成功完成的時候觸發此事件,this.result:來獲取讀取的檔案資料,如果是圖片,將返回base64格式的圖片資料)

下面為轉載的內容

拖放(drag-and-drop,DnD)其實是兩個動作——拖和放。所以,它涉及到兩個元素。一個是被拖的元素,稱為拖放源;另一個是要放的目標,稱為拖放目標。本文將通過拆分這兩個概念來詳細介紹原生拖放

拖放源

  什麼樣的元素才是拖放源呢?

  HTML5為所有HTML元素規定了一個draggable屬性,表示元素是否可以拖動

  影象和連結的draggable屬性自動被設定成了true,而其他元素這個屬性的預設值都是false

  [注意]必須設定draggable='true'才能生效,只設置draggable不起作用

  預設情況下,文字只有在被選中的情況下才能拖動,而影象和連結在任何時候都可以拖動。而其他元素則無法被拖放

<input value="文字可拖動">
<img alt="影象可拖動" src="http://files.cnblogs.com/files/xiaohuochai/zan.gif">
<a href="#">連結可拖動</a>
<div id="test" style="height:30px;width:300px;background:pink;">元素不可拖動</div>

  當為元素設定draggable屬性後,普通元素也可以拖動

<div draggable="true" style="height:30px;width:100px;background:pink;"></div>

相容

  IE9-瀏覽器不支援draggable屬性,但可通過mousedown事件處理程式呼叫dragDrop()方法來實現拖動效果

複製程式碼
<div id="test"  style="height:30px;width:300px;background:pink;"></div>    
<script>
test.onmousedown = function(){
    this.dragDrop();
}
</script>
複製程式碼

  [注意]如果讓firefox支援draggable屬性,必須新增一個ondragstart事件處理程式,並在dataTransfer物件使用setData()方法來啟動效果

拖放事件

  拖放源涉及到3個拖放事件。拖動拖放源時,依次觸發dragstart、drag和dragend這3個事件

dragstart

  按下滑鼠鍵並開始移動滑鼠時,會在被拖放的元素上觸發dragstart事件。此時游標變成“不能放”符號(圓環中有一條反斜線),表示不能把元素放到自己上面

drag

  觸發dragstart事件後,隨即會觸發drag事件,而且在元素被拖動期間會持續觸發該事件

dragend

  當拖動停止時(無論是把元素放到了有效的放置目標,還是放到了無效的放置目標上),會觸發dragend事件

複製程式碼
<div id="test"  draggable="true" style="height:30px;width:100px;background:pink;">0</div>    
<script>
var timer,i=0;
test.ondragstart = function(){
    this.style.backgroundColor = 'lightgreen';
}
test.ondrag = function(){
    if(timer) return;
    timer = setInterval(function(){
        test.innerHTML =  i++;
    },100)
}
test.ondragend = function(){
    clearInterval(timer);
    timer = 0;
    this.style.backgroundColor = 'pink';
}
</script>
複製程式碼

拖放目標

  拖放目標是指被拖動的元素鬆開滑鼠時被放置的目標

  拖放源被拖動到拖放目標上時,將依次觸發dragenter、dragover和dragleave或drop這四個事件

dragenter

  只要有元素被拖動到放置目標上,觸發dragenter事件

dragover

  被拖動的元素在放置目標的範圍內移動時,持續觸發dragover事件

dragleave

  如果元素被拖出了放置目標,觸發dragleave事件

drop

  如果元素被放到了放置目標中,觸發drop事件

  [注意]firefox瀏覽器的drop事件的預設行為是開啟被放到放置目標上的URL。為了讓firefox支援正常的拖放,還要取消drop事件的預設行為

  預設情況下,目標元素是不允許被放置的,所以不會發生drop事件。只要在dragover和dragenter事件中阻止預設行為,才能成為被允許的放置目標,才能允許發生drop事件。此時,游標變成了允許放置的符號

複製程式碼
<div id="test"  draggable="true" style="height:30px;width:130px;background:pink;float:left;">拖放源</div>    
<div id="target" style="float:right;height: 200px;width:200px;background:lightblue;">拖放目標</div>
<script>
var timer,i=0;
var timer1,i1=0;
//相容IE8-瀏覽器
test.onmousedown = function(){
    if(this.dragDrop){
        this.dragDrop();
    }
}
test.ondragstart = function(){
    this.style.backgroundColor = 'lightgreen';
    this.innerHTML = '開始拖動';
}
test.ondrag = function(){
    if(timer) return;
    timer = setInterval(function(){
        test.innerHTML =  '元素已被拖動' + ++i + '';
    },1000);
}
test.ondragend = function(){
    clearInterval(timer);
    timer = 0;i =0;
    this.innerHTML = '結束拖動';
    this.style.backgroundColor = 'pink';
}
target.ondragenter = function(e){
    e = e || event;
    if(e.preventDefault){
        e.preventDefault();
    }else{
        e.returnValue = false;
    }
    this.innerHTML = '有元素進入目標區域';
    this.style.background = 'red';
}
target.ondragover = function(e){
    e = e || event;
    if(e.preventDefault){
        e.preventDefault();
    }else{
        e.returnValue = false;
    }
    if(timer1) return;
    timer1 = setInterval(function(){
        target.innerHTML =  '元素已進入' + (++i1) + '';
    },1000);
}
target.ondragleave = function(){
    clearInterval(timer1);
    timer1 = 0;i1=0;
    this.innerHTML = '元素已離開目標區域';
    this.style.backgroundColor = 'lightblue';
}
target.ondrop = function(){
    clearInterval(timer1);
    timer1 = 0;i1=0;
    this.innerHTML = '元素已落在目標區域';
    this.style.backgroundColor = 'orange';    
}
</script>
複製程式碼

dataTransfer物件

  為了在拖放操作時實現資料交換,引入了dataTransfer物件,它是事件物件的一個屬性,用於從被拖動元素向放置目標傳遞字串格式的資料

  dataTransfer物件有兩個主要方法:getData()和setData()

  getData()可以取得由setData()儲存的值。setData()方法的第一個引數,也是getData()方法唯一的一個引數,是一個字串,表示儲存的資料型別,取值為"text"或"URL"

  IE只定義了"text"和"URL"兩種有效的資料型別,而HTML5則對此加以擴充套件,允許指定各種MIME型別。考慮到向後相容,HTML5也支援"text"和"URL",但這兩種型別會被對映為"text/plain"和"text/uri-list"

  實際上,dataTransfer物件可以為每種MIME型別都儲存一個值。換句話說,同時在這個物件中儲存一段文字和一個URL不會有任何問題

  [注意]儲存在dataTransfer物件中的資料只能在drop事件處理程式中讀取

  在拖動文字框中的文字時,瀏覽器會呼叫setData()方法,將拖動的文字以"text"格式儲存在dataTransfer物件中。類似地,在拖放連結或影象時,會呼叫setData()方法並儲存URL。然後,在這些元素被拖放到放置目標時,就可以通過getData()讀到這些資料

複製程式碼
<div>請將從這行文字中挑選一些移動到拖放目標中</div>    
<div id="target" style="margin-top:20px;height: 100px;width:200px;background:lightblue;">拖放目標</div>
<div id="result"></div>
<script>
target.ondragenter = function(e){
    e = e || event;
    if(e.preventDefault){
        e.preventDefault();
    }else{
        e.returnValue = false;
    }
    this.innerHTML = '有元素進入目標區域';
    this.style.background = 'red';
}
target.ondragover = function(e){
    e = e || event;
    if(e.preventDefault){
        e.preventDefault();
    }else{
        e.returnValue = false;
    }
}
target.ondragleave = function(e){
    e = e || event;    
    this.innerHTML = '元素已離開目標區域';
    this.style.backgroundColor = 'lightblue';
}
target.ondrop = function(e){
    e = e || event;
    if(e.preventDefault){
        e.preventDefault();
    }else{
        e.returnValue = false;
    }
    result.innerHTML = '落入目標區域的文字為:' + e.dataTransfer.getData('text');
    this.innerHTML = '元素已落在目標區域';
    this.style.backgroundColor = 'orange';    
}
</script>
複製程式碼

  當然,也可以在dragstart事件處理程式中呼叫setData(),手動儲存自己要傳輸的資料,以便將來使用

複製程式碼
<div id="test" draggable="true" data-value="這是一個祕密" style="height:30px;width:100px;background:pink;">拖動源</div>    
<div id="target" style="margin-top:20px;height: 100px;width:200px;background:lightblue;">拖放目標</div>
<div id="result"></div>
<script>
 //相容IE8-瀏覽器
test.onmousedown = function(){
    if(this.dragDrop){
        this.dragDrop();
    }
}
test.ondragstart = function(e){
    e = e || event;
    e.dataTransfer.setData('text',test.getAttribute('data-value'));
}
target.ondragenter = function(e){
    e = e || event;
    if(e.preventDefault){
        e.preventDefault();
    }else{
        e.returnValue = false;
    }
    this.innerHTML = '有元素進入目標區域';
    this.style.background = 'red';
}
target.ondragover = function(e){
    e = e || event;
    if(e.preventDefault){
        e.preventDefault();
    }else{
        e.returnValue = false;
    }
}
target.ondragleave = function(e){
    e = e || event;    
    this.innerHTML = '元素已離開目標區域';
    this.style.backgroundColor = 'lightblue';
}
target.ondrop = function(e){
    e = e || event;
    if(e.preventDefault){
        e.preventDefault();
    }else{
        e.returnValue = false;
    }
    result.innerHTML = '落入目標區域的文字為:' + e.dataTransfer.getData('text');
    this
            
           

相關推薦

深入理解原生jsdraggable

本來是打算要自己總結的,但發現了一篇比較好的部落格,把我想寫的都寫了,甚至更加全面,所以,我只把我認為比較重要的知識點提煉一下,其他的都是轉載的,想看原博主的請點選原生js拖放提煉知識點:.draggable:設定為true,元素就可以拖拽了拖拽元素事件:事件物件為被拖拽元素

3.2《深入理解計算機系統》筆記內存和高速緩存的原理【插圖】

img sram 本質 text ddr rate too 是我 很大的 《深入計算機系統》筆記(一)主要是講解程序的構成、執行和控制。接下來就是運行了。我跳過了“處理器體系結構”和“優化程序性能”,這兩章的筆記繼續往後延遲! 《深入計算機系統》的一個很大的用處

深入理解Java內存模型——鎖

運行 包含 示意圖 支持 ole img api turn before 本文轉自:http://www.infoq.com/cn/articles/java-memory-model-5 鎖的釋放-獲取建立的happens before 關系 鎖是java並發編程中最重要

深入理解Java內存模型——順序一致性

內存空間 寫入 方便 語言 body 一半 同步 java語言 post 本文轉自:http://www.infoq.com/cn/articles/java-memory-model-3 數據競爭與順序一致性保證 當程序未正確同步時,就會存在數據競爭。java內存模型規範

深入理解Java內存模型——volatile

繼續 表現 可能 class 之前 art 其他 reader int 本文轉自:http://www.infoq.com/cn/articles/java-memory-model-4 volatile的特性 當我們聲明共享變量為volatile後,對這個變量的讀/寫將會

深入理解JVM虛擬機:Java運行時數據區域

字面量 符號 地方 64位 因此 lower 優化 java堆大小 工作 概述 JVM是Java語言的精髓所在,因為它Java語言實現了跨平臺運行,以及自動內存管理機制等,本文將從概念上介紹JVM內存的各個區域,說明個區域的作用。 JVM運行時數據區模型 Java虛擬機在執

深入理解計算機系統配套實驗 data lab 函式詳解

/* 135. * bitAnd - x&y using only ~ and | 136. * Example: bitAnd(6, 5) = 4 137. * Legal ops: ~ | 138. * Max ops: 8 139. *

深入理解Java類載入機制

1 前言: 在上一篇文章一文讓你明白 Java 位元組碼中, 我們瞭解了java位元組碼的解析過程,那麼在接下來的內容中,我們來了解一下類的載入機制。 2 題外話 Java的核心是什麼?當然是JVM了,所以說了解並熟悉JVM對於我們理解Java語言非常重要,不管你是做Java還是Andr

深入理解Java Class檔案格式

經過前八篇關於class檔案的部落格, 關於class檔案格式的內容也基本上講完了。 本文是關於class檔案格式的最後一篇。 在這篇部落格中, 將會講解關於方法的幾個屬性。 理解這篇部落格的內容, 對於理解JVM執行引擎起著重要作用。 關於虛擬機器執行引擎有關的內容, 會在本專欄後面的部落格中涉及

深入理解Java Class檔案格式

在本專欄的第一篇文章 深入理解Java虛擬機器到底是什麼 中, 我們主要講解了什麼是虛擬機器, 這篇部落格是對JVM的一個概述。 在隨後的幾篇文章中,一直在講解class檔案格式。 在今天這篇部落格中, 將會繼續講解class檔案中的其他資訊。 在本文中, 將會講解class檔案中的最後一

深入理解Java Class檔案格式

本專欄列前面的一系列部落格, 對Class檔案中的一部分資料項進行了介紹。 本文將會繼續介紹class檔案中未講解的資訊。 先回顧一下上面一篇文章。 在上一篇部落格中, 我們介紹了: this_class    對當前類的描述 super_class  &

深入理解Java Class檔案格式

經過前幾篇文章, 終於將常量池介紹完了, 之所以花這麼大的功夫介紹常量池, 是因為對於理解class檔案格式,常量池是必須要了解的, 因為class檔案中其他地方,大量引用了常量池中的資料項。  對於還不瞭解常量池的讀者, 如果想要深入瞭解class檔案格式, 或者想繼續讀這篇部落格和本專

深入理解java多執行緒

關於java多執行緒的概念以及基本用法:java多執行緒基礎 6,單例模式與多執行緒 如何使單例模式遇到多執行緒是安全的這是下面要討論的內容 6.1,立即載入 立即載入就是在使用類的時候已經將物件建立完畢,例如String s = new Stri

深入理解Java多執行緒

關於java多執行緒的概念以及基本用法:java多執行緒基礎 5,定時器Timer JDK中Timer類主要是負責計劃任務的功能,也就是在指定的時間開始執行某一個任務,封裝任務的類是TimerTask類,執行計劃任務的程式碼要放進TimerTask的子類,因為它一個抽象

深入理解Java多執行緒

關於java多執行緒的概念以及基本用法:java多執行緒基礎 4,Lock的使用 ReentrantLook類的使用 ReentrantReadWriteLock類的使用 4.1,ReentrantLook類的使用 新建MySe

深入理解Java多執行緒

關於java多執行緒的概念以及基本用法:java多執行緒基礎 3, 執行緒間通訊 執行緒在作業系統中是獨立的個體,經過特殊的處理,執行緒間可以實現通訊,進而成為一個整體,提高CPU利用率 3.1,等待/通知機制 等待:wait()方法作用是使當前執

深入理解Java多執行緒

關於java多執行緒的概念以及基本用法:java多執行緒基礎 2,多執行緒的同步 多個執行緒對同一物件的變數進行同時訪問時會引發執行緒的安全問題,即一個執行緒對一個變數修改後,其他執行緒可能會讀取到修改後的變數值,所以我們要對獲得的例項變數的值進行同步處理,保證其原子性

深入理解Java多執行緒

關於java多執行緒的概念以及基本用法:java多執行緒基礎 1,停止執行緒 停止執行緒意味著線上程執行完之前停止正在做的操作,即立刻放棄當前的操作,這並不容易。停止執行緒可以用Thread.stop()方法,但是這個方法不安全,所以不建議使用,還有一個方法就是Thre

深入理解java中的介面 Interface

概念 我們知道java中是單繼承的,這就有了很多的限制,比如我們需要多繼承的時候但是不能用多繼承,這時候怎麼辦呢?就引入了介面的概念,它彌補了java中單繼承的缺陷,這一點非常的好,如果要約定子類的實現要求並避免單繼承侷限就需要使用介面。 那麼什麼是介面呢?

原生JS去重--兩種方法去掉重複字元

所謂“去重”,即是去掉重複的字元。本篇部落格講述兩種方式去重,一種是比較簡單但程式碼比較囉嗦點的,另一種是有點深度但是簡潔的。  我直接寫JavaScript程式碼了。  方式一: function deleteRepetionChar(arr){ //先判斷輸入進