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