HTML5原生拖拽/拖放(drag drop)详解
前言
拖放(drap && drop)在我們平時(shí)的工作中,經(jīng)常遇到。它表示:抓取對(duì)象以后拖放到另一個(gè)位置。目前,它是HTML5標(biāo)準(zhǔn)的一部分。我從幾個(gè)方面學(xué)習(xí)并實(shí)踐這個(gè)功能。
拖放的流程對(duì)應(yīng)的事件
我們先看下拖放的流程:
選中 ---> 拖動(dòng) ---> 釋放然后,我們一步步看下這個(gè)過(guò)程中,會(huì)發(fā)生的事情。
選中
在HTML5標(biāo)準(zhǔn)中,為了使元素可拖動(dòng),把draggable屬性設(shè)置為true。
文本、圖片和鏈接是默認(rèn)可以拖放的,它們的draggable屬性自動(dòng)被設(shè)置成了true。
圖片和鏈接按住鼠標(biāo)左鍵選中,就可以拖放。
文本只有在被選中的情況下才能拖放。如果顯示設(shè)置文本的draggable屬性為true,按住鼠標(biāo)左鍵也可以直接拖放。
draggable屬性:設(shè)置元素是否可拖動(dòng)。
語(yǔ)法:<element draggable="true | false | auto" >
- true: 可以拖動(dòng)
- false: 禁止拖動(dòng)
- auto: 跟隨瀏覽器定義是否可以拖動(dòng)
拖動(dòng)
每一個(gè)可拖動(dòng)的元素,在拖動(dòng)過(guò)程中,都會(huì)經(jīng)歷三個(gè)過(guò)程,拖動(dòng)開(kāi)始-->拖動(dòng)過(guò)程中--> 拖動(dòng)結(jié)束。
| 被拖動(dòng)的元素 | dragstart | 在元素開(kāi)始被拖動(dòng)時(shí)候觸發(fā) |
| drag | 在元素被拖動(dòng)時(shí)反復(fù)觸發(fā) | |
| dragend | 在拖動(dòng)操作完成時(shí)觸發(fā) | |
| 目的地對(duì)象 | dragenter | 當(dāng)被拖動(dòng)元素進(jìn)入目的地元素所占據(jù)的屏幕空間時(shí)觸發(fā) |
| dragover | 當(dāng)被拖動(dòng)元素在目的地元素內(nèi)時(shí)觸發(fā) | |
| dragleave | 當(dāng)被拖動(dòng)元素沒(méi)有放下就離開(kāi)目的地元素時(shí)觸發(fā) |
dragenter和dragover事件的默認(rèn)行為是拒絕接受任何被拖放的元素。因此,我們必須阻止瀏覽器這種默認(rèn)行為。e.preventDefault();
釋放
到達(dá)目的地之后,釋放元素事件
| 目的地對(duì)象 | drop | 當(dāng)被拖動(dòng)元素在目的地元素里放下時(shí)觸發(fā),一般需要取消瀏覽器的默認(rèn)行為。 |
選中拖動(dòng)釋放例子
<!DOCTYPE HTML> <html><head><title>拖放示例-文本</title> </head> <style> .src {display: flex; }.dropabled {flex: 1; }.txt {color: green; }.img {width: 100px;height: 100px;border: 1px solid gray; }.target {width: 200px;height: 200px;line-height: 200px;text-align: center;border: 1px solid gray;color: red; } </style><body><div class="src"><div class="dragabled"><div class="txt" id="txt">所有的文字都可拖拽。<p draggable="true">此段文字設(shè)置了屬性draggable="true"</p> </div><div class="url" id="url"><a href="http://weiqinl.com" target="_blank">我是url:http://weiqinl.com</a></div><img class="img" id="tupian1" src="img1.png" alt="圖片1" /><img class="img" id="tupian2" src="img2.png" alt="圖片2" /></div><div id='target' class="dropabled target">Drop Here</div></div><script>var dragSrc = document.getElementById('txt')var target = document.getElementById('target')dragSrc.ondragstart = handle_startdragSrc.ondrag = handle_dragdragSrc.ondragend = handle_endfunction handle_start(e) {console.log('dragstart-在元素開(kāi)始被拖動(dòng)時(shí)候觸發(fā)')}function handle_drag() {console.log('drag-在元素被拖動(dòng)時(shí)候反復(fù)觸發(fā)')}function handle_end() {console.log('dragend-在拖動(dòng)操作完成時(shí)觸發(fā)')}target.ondragenter = handle_entertarget.ondragover = handle_overtarget.ondragleave = handle_leavetarget.ondrop = handle_dropfunction handle_enter(e) {console.log('handle_enter-當(dāng)元素進(jìn)入目的地時(shí)觸發(fā)')// 阻止瀏覽器默認(rèn)行為e.preventDefault()}function handle_over(e) {console.log('handle_over-當(dāng)元素在目的地時(shí)觸發(fā)')// 阻止瀏覽器默認(rèn)行為e.preventDefault()}function handle_leave(e) {console.log('handle_leave-當(dāng)元素離開(kāi)目的地時(shí)觸發(fā)')// 阻止瀏覽器默認(rèn)行為// e.preventDefault()}function handle_drop(e) {console.log('handle_drop-當(dāng)元素在目的地放下時(shí)觸發(fā)')var t = Date.now()target.innerHTML = ''target.append(t + '-拖放觸發(fā)的事件。')e.preventDefault()}</script> </body></html>drag-drop事件觸發(fā)
在整個(gè)拖放過(guò)程中,我們以上說(shuō)的是表面現(xiàn)象,事件過(guò)程內(nèi)部還會(huì)發(fā)生什么事情呢?請(qǐng)看下面?的DataTransfer對(duì)象。
DataTransfer對(duì)象
與拖放操作所觸發(fā)的事件同時(shí)派發(fā)的對(duì)象是DragEvent,它派生于MouseEvent,具有Event與MouseEvent對(duì)象的所有功能,并增加了dataTransfer屬性。該屬性用于保存拖放的數(shù)據(jù)和交互信息,返回DataTransfer對(duì)象。
// DataTransfer dataTransfer = DragEvent.dataTransfer
DataTransfer對(duì)象定義的屬性和方法有很多種,我們看下列入標(biāo)準(zhǔn)的幾個(gè)。
| types | 只讀屬性。它返回一個(gè)我們?cè)赿ragstart事件中設(shè)置的拖動(dòng)數(shù)據(jù)格式的數(shù)組。 格式順序與拖動(dòng)操作中包含的數(shù)據(jù)順序相同。IE10+、Edge、safari3.1、Firefox3.5+ 和Chrome4以上支持該屬性 |
| files | 返回拖動(dòng)操作中的文件列表。包含一個(gè)在數(shù)據(jù)傳輸上所有可用的本地文件列表。如果拖動(dòng)操作不涉及拖動(dòng)文件,此屬性是一個(gè)空列表。 |
| dropEffect | 獲取當(dāng)前選定的拖放操作的類(lèi)型或?qū)⒉僮髟O(shè)置為新類(lèi)型。它應(yīng)該始終設(shè)置成effectAllowed的可能值之一【none、move、copy、link】。dragover事件處理程序中針對(duì)放置目標(biāo)來(lái)設(shè)置dropEffect。 |
| effectAllowed | 指定拖放操作所允許的效果。必須是其中之一【 none, copy, copyLink, copyMove, link, linkMove, move, all, uninitialized】默認(rèn)為uninitialized 表示允許所有的效果。ondragstart處理程序中設(shè)置effectAllowed屬性 |
| void setData(format, data) | 將拖動(dòng)操作的拖動(dòng)數(shù)據(jù)設(shè)置為指定的數(shù)據(jù)和類(lèi)型。format可以是MIME類(lèi)型 |
| String getData(format) | 返回指定格式的數(shù)據(jù),format與setData()中一致 |
| void clearData([format]) | 刪除給定類(lèi)型的拖動(dòng)操作的數(shù)據(jù)。如果給定類(lèi)型的數(shù)據(jù)不存在,此方法不執(zhí)行任何操作。如果不給定參數(shù),則刪除所有類(lèi)型的數(shù)據(jù)。 |
| void setDragImage(img, xOffset, yOffset) | 指定一副圖像,當(dāng)拖動(dòng)發(fā)生時(shí),顯示在光標(biāo)下方。大多數(shù)情況下不用設(shè)置,因?yàn)楸煌蟿?dòng)的節(jié)點(diǎn)被創(chuàng)建成默認(rèn)圖片。x,y參數(shù)分別指示圖像的水平、垂直偏移量 |
drag-drop-dataTransfer各屬性方法示例
瀏覽器支持程度
說(shuō)了這么多,如果瀏覽器不支持,也是白扯。
Method of easily dragging and dropping elements on a page, requiring minimal JavaScript.
要求最少的js,實(shí)現(xiàn)拖拽頁(yè)面元素的簡(jiǎn)單方法
drag之瀏覽器支持程度--caniuse

note
- dataTransfer.items 只有Chrome支持
- dropzone屬性,目前沒(méi)有瀏覽器支持
- Firefox支持.setDragImage任何類(lèi)型的DOM元素。Chrome必須有HTMLImageElement或者任何DOM元素,該DOM元素附加到DOM 和瀏覽器的.setDragImage視口(viewport)內(nèi)。
1.部分支持是指不支持dataTransfer.files 或者 .types對(duì)象
2.部分支持是指不支持.setDragImage
3.部分支持是指dataTransfer.setData / getData 的有限支持格式
以下,我在實(shí)際中遇到的情況,各瀏覽器對(duì)標(biāo)準(zhǔn)的實(shí)現(xiàn)還是有差異的。
- getData()在chrome 62.0瀏覽器中,只能在drop事件中生效。
- 如果使用setDragImage方法,指定的圖像不存在,則拖動(dòng)過(guò)程:
- safari 11.0.1 瀏覽器,只會(huì)觸發(fā)dragstart和dragend事件。
- chrome、opera 和 Firefox會(huì)正常觸發(fā)其他事件。
- 每一次拖放操作,Firefox都會(huì)執(zhí)行一次新開(kāi)一個(gè)頁(yè)面的動(dòng)作,并且自動(dòng)搜索dataTransfer.getData()得到的內(nèi)容。
解決方法,在drop事件中,添加: e.stopPropagation();// 不再派發(fā)事件。解決Firefox瀏覽器,打開(kāi)新窗口的問(wèn)題。 - opera 49版本中,鏈接默認(rèn)不可以拖動(dòng),必須把draggable屬性設(shè)置為true,才可以拖動(dòng)。
- 關(guān)于 dropEffect 和 effectAllowed 。
- effectAllowed 允許拖放操作的效果,最多不會(huì)超過(guò)那么幾種。dropEffect 設(shè)置拖放操作的具體效果,只能是四種可能之一。
- 如果effectAllowed設(shè)置為none,則不允許拖放元素。但是各個(gè)瀏覽器能觸發(fā)的事件不一樣。(注意:safari可以拖放元素,而且會(huì)觸發(fā)所有事件)
- 如果dropEffect設(shè)置為none,則不允許被拖放到目的地元素中。
- 如果設(shè)置了effectAllowed的值,那么如果要設(shè)置dropEffect的值,其值必須和effectAllowed的值一致,否則拖動(dòng)效果無(wú)效,而且不允許將被拖放元素放到目的地元素中。(注:safari11.0.1有效果,而且也能拖動(dòng)到目的地元素中,但是這不符合標(biāo)準(zhǔn))。
示例
drag-drop-dataTransfer各屬性方法示例
drag-drop事件觸發(fā)
總結(jié)
原生HTML5拖拽API,drag && drop 在實(shí)際工作中,還是有很多情況下會(huì)遇到的。
以上,我只介紹了部分常用API。API不復(fù)雜,多看會(huì)兒,實(shí)踐就知道了。各個(gè)瀏覽器,可能會(huì)在表現(xiàn)上,稍有不同,但我相信大家還是會(huì)向著標(biāo)準(zhǔn)發(fā)展的。
轉(zhuǎn)載于:https://www.cnblogs.com/weiqinl/p/7886049.html
總結(jié)
以上是生活随笔為你收集整理的HTML5原生拖拽/拖放(drag drop)详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 做梦梦到楼房漏水是什么意思
- 下一篇: 梦到偷豆角是什么意思