HTML5 Drag & Drop 是一組定義拖放行爲的API,若是你想開發在線Excel之類富交互的應用,它應該能幫你節省很多時間。html
拖放過程由兩個部分構成:canvas
被拖拽的元素,以後簡稱爲子項(item)瀏覽器
放置被拖拽元素的元素,以後簡稱爲容器(container)app
一個將子項拖進容器的簡單功能,CSS略過,以jQuery操做DOM:this
<div id="container"></div> <div id="item" draggable></div>
$('#container').on('dragover', function(e){ e.preventDefault() }) $('#container').on('drop', function(e){ $('#item').appendTo(this) })
首先在子項上添加draggable
屬性,代表元素能夠被拖拽(發覺在Chrome中不加也能夠。)url
容器的dragover
事件必須禁止默認事件,不然這個容器不容許放置子項。spa
容器的drop
事件在子項放置到容器後觸發。指針
能夠看到,這組API只會提供簡單的行爲與事件接口,拖放後會發生什麼,仍是得由咱們本身來實現。code
dragstart - 拖拽開始htm
drag - 拖拽過程當中不斷觸發
dragend - 拖拽結束,不管有沒有拖進容器( 鼠標鬆開就觸發 )
這3個事件與touch
系列事件很類似。
dragenter - 子項進入容器範圍
dragover - 子項在容器範圍內不斷觸發
dragleave - 子項離開容器範圍
drop - 拖拽結束,且子項成功拖進容器
前3個事件與mouse
系列事件很類似。
注意,放開鼠標時,不管子項有沒有拖進容器,都必定會觸發子項的
dragend
事件,表示拖拽行爲的完結;而只有成功拖進容器,纔會觸發容器的drop
事件,表示確實落地了。
dataTransfer
是這組API的核心對象,提供了許多實用功能。
dataTransfer
能夠傳遞數據:
$('#item').on('dragstart', function(e){ e.originalEvent.dataTransfer.setData('name', 'kid') e.originalEvent.dataTransfer.setData('age', 18) }) $('#container').on('dragover', function(e){ e.preventDefault() }) $('#container').on('drop', function(e){ e.originalEvent.dataTransfer.getData('NAME') // => 'kid' e.originalEvent.dataTransfer.getData('age') // => '18' })
由於這裏使用了jQuery,因此是
e.originalEvent.dataTransfer
,若用原生方式綁定事件,則爲e.dataTransfer
。
key
不區分大小寫,因此'name'
中的值,用'NAME'
也能取出來。若key
不存在,則返回空字符串。
value
一概轉換爲字符串,因此數字age
存的是數字,但取出來是字符串。
當key
爲URL
時,若value
爲一個合法的url值(好比'http://www.baidu.com'
),則拖拽到瀏覽器地址欄或標籤欄會打開對應頁面。
用clearData
能夠清除數據,但只能在dragstart
中進行,用處不大:
$('#item').on('dragstart', function(e){ e.originalEvent.dataTransfer.setData('name', 'kid') e.originalEvent.dataTransfer.setData('age', 18) e.originalEvent.dataTransfer.clearData('name') // 若不指定key,則清除全部數據 }) $('#container').on('dragover', function(e){ e.preventDefault() }) $('#container').on('drop', function(e){ var a = e.originalEvent.dataTransfer.getData('NAME') // => '' var b = e.originalEvent.dataTransfer.getData('age') // => '18' })
容器能夠用dataTransfer.dropEffect
設置一個類型,它指示了進入本容器的子項會發生什麼效果:
move - 移動子項到容器
copy - 複製子項到容器
link - 打開連接
none - 禁止任何子項放置在此容器
這個效果不會自動發生。試一試就知道了,當子項拖入容器範圍,則鼠標指針會變成相應類型的外觀(由瀏覽器設定)。這是針對用戶的簡單提示,而不是說設置爲copy
就會自動複製子項。仍是那句話,由你來具體實現。
與此對應,子項經過dataTransfer.effectAllowed
屬性可限定本身着陸的容器類型:
move
copy
link
copyMove - copy
或move
copyLink - copy
或link
linkMove - link
或move
all - move
或copy
或link
uninitialized - 默認值,等價於all
none - 禁止在任何容器着陸
實際使用看看:
$('#item').on('dragstart', function(e){ e.originalEvent.dataTransfer.effectAllowed = 'all' }) $('#container').on('dragover', function(e){ e.preventDefault() }) $('#container').on('drop', function(e){ e.originalEvent.dataTransfer.dropEffect = 'copy' })
若二者不匹配,則子項沒法放置到容器中。
在相冊類應用中,拖拽照片是一個常見功能。咱們能夠用setDragImage
方法來設置一張圖片,在拖拽過程當中跟隨鼠標移動:
var img = new Image() img.src = 'face-small.png' $('#item').on('dragstart', function(e){ e.originalEvent.dataTransfer.setDragImage(img, 100, 100) })
第一個參數設置圖片,後兩個參數設置鼠標相對圖片的位置。好比這張圖的大小是200×200,我設置100表示鼠標在圖片正中心,效果示意:
另外,setDragImage
也能夠接收Canvas圖像,簡單示例:
<canvas width="200", height="200"></canvas>
var canvas = $('canvas')[0] var ctx = canvas.getContext('2d') ctx.fillStyle="pink" ctx.fillRect(0, 0, 200, 200) $('#item').on('dragstart', function(e){ e.originalEvent.dataTransfer.setDragImage(canvas, 100, 100) })
最後說一下,這組API如今基本只能用於PC端:
原創,自由轉載,請署名,本人博客 kid-wumeng.me