摘要:前言拖動是添加的提供了元素拖動的原生支持拖動相對于其他的事件復(fù)雜了一些原因就在于拖動是被拖動元素與被放置元素的互動涉及到了兩個元素而不是一個導(dǎo)致流程的復(fù)雜但是其中的很多設(shè)計是有規(guī)律可循的現(xiàn)在我們來看一個基本的使用場景這里有兩個元素和是可拖動
前言
拖動api是HTML5添加的API,提供了元素拖動的原生支持
拖動API相對于其他的事件API復(fù)雜了一些,原因就在于拖動是被拖動元素與被放置元素的互動涉及到了兩個元素,而不是一個導(dǎo)致流程的復(fù)雜,但是其中的很多設(shè)計是有規(guī)律可循的.
現(xiàn)在我們來看一個基本的使用場景,這里有兩個元素A和B,A是可拖動元素而B是可放置元素,我們將A放置到B中
鼠標(biāo)按下后拖動元素A,觸發(fā)A的dragstart事件
開始移動A元素
剛剛觸碰到B容器,觸發(fā)B的dragenter事件
移動到B上方
觸發(fā)B容器的dragover事件,該事件類似于mouseover事件是連續(xù)觸發(fā)的
松開鼠標(biāo)放置A
觸發(fā)B容器的drop事件
觸發(fā)A元素的dragend事件
基本流程我們來實現(xiàn)上面的幾個步驟
html
目標(biāo)區(qū)域
注意:被拖動的元素需要設(shè)置draggable屬性
css
html, body { height: 100%; } html, body, div { margin: 0; padding: 0; box-sizing: border-box; } #test { margin: 0 auto; margin-top: 10%; width: 50%; height: 50%; background: #4CB8C4; background: linear-gradient(to right, #3CD3AD, #4CB8C4); box-shadow: 0 0 15px -3px black; } #display { margin: 0 auto; margin-top: 10%; width: 30%; height: 30%; background-color: rgba(0, 0, 0, 0.055); }
javascript
let dargElem = document.getElementById("test"); let targetElem = document.getElementById("display"); dargElem.addEventListener("dragstart", (event) => { // 被拖動元素開始事件 console.log(event); }) // 拖動結(jié)束事件 dargElem.addEventListener("dragend", (event) => { console.log("拖動結(jié)束事件"); }) // 進入容器的事件 targetElem.addEventListener("dragenter", (event) => { event.preventDefault(); console.log("拖動進入事件"); }) // 懸浮到容器上方的事件 targetElem.addEventListener("dragover", (event) => { event.preventDefault(); }) // 拖動事件 targetElem.addEventListener("drop", (event) => { console.log("觸發(fā)放置事件") })
這個例子中dargElem保存的是被拖動元素,我們?yōu)樗粤?b>dragstart和dragend事件,
另外一個變量targetElem是容器元素我們?yōu)樗粤?b>dragenter dragover drop 事件
控制臺輸出:
開始拖動 拖動進入事件 觸發(fā)放置事件 拖動結(jié)束事件
注意:這個例子中使用了event.preventDefault()用于阻止默認(rèn)的行為,例如拖動a標(biāo)簽的時候有可能觸發(fā)默認(rèn)的跳轉(zhuǎn)行為
所有事件列表(不包含廠商事件和瀏覽器不支持事件):
被拖動的對象
dragstart 拖動開始觸發(fā)
drag 拖動過程中觸發(fā) 連續(xù)觸發(fā)
dragend 拖動結(jié)束后觸發(fā)
被當(dāng)作容器的元素
dragenter 元素進入時候觸發(fā)
dragover 可拖動元素置于容器元素上方時觸發(fā) 連續(xù)觸發(fā)
drop 可拖動元素置入到容器元素中觸發(fā)
dragleave 可拖動元素移動出容器元素時候觸發(fā)
注意:容器元素一定需要監(jiān)聽dragover事件并且一開始調(diào)用event.preventDefault()后續(xù)的drop才會觸發(fā)dragover相當(dāng)于是一個過濾器,只允許指定的元素可以觸發(fā)drop事件
數(shù)據(jù)的交互前面說道拖動事件是兩個元素的互動,但是僅僅使用事件是不夠的,我們需要其他的手段在兩個元素之間傳遞信息
在dragstart事件觸發(fā)的時候所提供的event對象中含有一個DataTransfer對象,這個對象允許在多個事件中保存信息且在所有拖動事件中存在
簡單信息傳遞操作:
被拖動元素調(diào)用該對象的setData()方法設(shè)置值
容器元素在drop事件中使用event對象的DataTransfer屬性的getData()方法獲取在dragstart事件中設(shè)置的值
例子:
let dargElem = document.getElementById("test"); let targetElem = document.getElementById("display"); dargElem.addEventListener("dragstart", (event) => { event.dataTransfer.setData("test",[1,2,3]); }) // 必須設(shè)置 targetElem.addEventListener("dragover", (event) => { event.preventDefault(); }) // 拖動事件 targetElem.addEventListener("drop", (event) => { event.preventDefault(); console.log(event.dataTransfer.getData("test")); })
可以看到DataTransfer數(shù)據(jù)的設(shè)置就是典型的鍵值操作而已
綜合實例一個來自MDN的例子:
html
This div is draggable
css
#draggable { width: 200px; height: 20px; text-align: center; background: white; } .dropzone { width: 200px; height: 20px; background: blueviolet; margin-bottom: 10px; padding: 10px; }
javascript
var dragged; /* 可拖動的目標(biāo)元素會觸發(fā)事件 */ document.addEventListener("drag", function( event ) { }, false); document.addEventListener("dragstart", function( event ) { // 保存拖動元素的引用(ref.) dragged = event.target; // 使其半透明 event.target.style.opacity = .5; }, false); document.addEventListener("dragend", function( event ) { // 重置透明度 event.target.style.opacity = ""; }, false); /* 放下目標(biāo)節(jié)點時觸發(fā)事件 */ document.addEventListener("dragover", function( event ) { // 阻止默認(rèn)動作 event.preventDefault(); }, false); document.addEventListener("dragenter", function( event ) { // 當(dāng)可拖動的元素進入可放置的目標(biāo)高亮目標(biāo)節(jié)點 if ( event.target.className == "dropzone" ) { event.target.style.background = "purple"; } }, false); document.addEventListener("dragleave", function( event ) { // 當(dāng)拖動元素離開可放置目標(biāo)節(jié)點,重置其背景 if ( event.target.className == "dropzone" ) { event.target.style.background = ""; } }, false); document.addEventListener("drop", function( event ) { // 阻止默認(rèn)動作(如打開一些元素的鏈接) event.preventDefault(); // 移動拖動的元素到所選擇的放置目標(biāo)節(jié)點 if ( event.target.className == "dropzone" ) { event.target.style.background = ""; dragged.parentNode.removeChild( dragged ); event.target.appendChild( dragged ); } }, false);DataTransfer詳解
DataTransfer不僅僅用于元素之間信息的傳遞,同時可以控制拖動的樣式,以及傳遞額外的信息
屬性:
dropEffect 類型 String
effectAllowed 類型 String
files 類型 FileList
types 類型 DOMStringList
方法:
void addElement(in Element element)
void clearData([in String type])
String getData(in String type)
void setData(in String type, in String data)
void setDragImage(in nsIDOMElement image, in long x, in long y)
這里只講解一下dropEffect和effectAllowed因為這里有坑files屬性用于從瀏覽器外部拖入文件時候使用types使用較少這里不提了
提供MDN鏈接,看完本文后可以查閱剩下的方法和屬性:
https://developer.mozilla.org...
dropEffect和effectAllowed用于控制拖動的時候光標(biāo)角標(biāo)的樣式,過濾不同的類型拖動行為
dropEffect可能的值:
copy: 復(fù)制到新的位置
move: 移動到新的位置.
link: 建立一個源位置到新位置的鏈接.
none: 禁止放置(禁止任何操作).
effectAllowed可能的值:
copy: 復(fù)制到新的位置.
move:移動到新的位置 .
link:建立一個源位置到新位置的鏈接.
copyLink: 允許復(fù)制或者鏈接.
copyMove: 允許復(fù)制或者移動.
linkMove: 允許鏈接或者移動.
all: 允許所有的操作.
none: 禁止所有操作.
uninitialized: 缺省值(默認(rèn)值), 相當(dāng)于 all.
簡單來說在被拖動元素的事件中設(shè)置effectAllowed屬性表示期待的拖動樣式,而在容器元素中設(shè)置dropEffect表示容器指定的樣式,其他的設(shè)置都會被忽視
對于dropEffect只有在dragover事件中中修改值才會影響樣式,我用的是Chrome66
對于effectAllowed只有在dragstart事件中有效
例子雙方都使用link樣式:
let dargElem = document.getElementById("test"); let targetElem = document.getElementById("display"); // 拖動開始事件 dargElem.addEventListener("dragstart", (event) => { event.dataTransfer.effectAllowed = "link"; }) // 懸浮到容器上方的事件 targetElem.addEventListener("dragover", (event) => { event.dataTransfer.dropEffect = "link"; event.preventDefault(); }) // 拖動事件 targetElem.addEventListener("drop", (event) => { console.log("pass") event.preventDefault(); })
這個例子中drop事件被觸發(fā)
例子effectAllowed設(shè)置為copy而dropEffect設(shè)置為link:
let dargElem = document.getElementById("test"); let targetElem = document.getElementById("display"); // 拖動開始事件 dargElem.addEventListener("dragstart", (event) => { event.dataTransfer.effectAllowed = "link"; }) // 懸浮到容器上方的事件 targetElem.addEventListener("dragover", (event) => { event.dataTransfer.dropEffect = "link"; event.preventDefault(); }) // 拖動事件 targetElem.addEventListener("drop", (event) => { console.log("pass") event.preventDefault(); })
這個例子執(zhí)行的結(jié)果就是拖動時候的角標(biāo)一直是禁止符號,在容器元素上松開也不會觸發(fā)drop事件
參考鏈接https://developer.mozilla.org...https://developer.mozilla.org...
https://blog.csdn.net/baidu_3...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/96738.html
摘要:回調(diào)函數(shù)回調(diào)函數(shù)文件夾拖動攔截默認(rèn)行為,并阻止冒泡文件夾拖動或者文件拖動,瀏覽器默認(rèn)會直接打開顯示,圖片尤為明顯,所以首先需要阻止默認(rèn)行為。 前言 文件拖動上傳,對于個別應(yīng)用場景十分有效,實現(xiàn)起來也并不難。參見 瀏覽器圖片預(yù)覽 --http://blog.segmentfault.com/bornkiller/1190000000428572。 現(xiàn)在更進一步,做到文件夾拖動。Fils...
摘要:該區(qū)域代表可以被所控制的畫布。那么現(xiàn)在第二個問題,識別該文檔,這或許不是大部分用戶的需求,但小部分用戶并不意味著人數(shù)少。因此一個基于的請求于標(biāo)準(zhǔn)內(nèi)提出。 前言 作為程序員,技術(shù)的落實與鞏固是必要的,因此想到寫個系列,名為 why what or how 每篇文章試圖解釋清楚一個問題。 這次的 why what or how 主題:現(xiàn)在幾乎所有人都知道了 HTML5 ,那么 H5 到底相...
閱讀 2805·2019-08-30 15:55
閱讀 2853·2019-08-30 15:53
閱讀 2289·2019-08-26 13:47
閱讀 2551·2019-08-26 13:43
閱讀 3153·2019-08-26 13:33
閱讀 2794·2019-08-26 11:53
閱讀 1789·2019-08-23 18:35
閱讀 795·2019-08-23 17:16