HTML5 的拖拽介绍
本文主要介绍与拖拽操作相关的对象及事件信息,但并不涉及太多的源码演示。
一个简单的示例
在html5中要实现拖放操作,相对于以前通过鼠标操作实现,要简单得多,数据安全性也更有保障。只需要以下几步即可。
- 给被拖拽元素添加
draggable
属性,如果是文件拖放。 - 为目标元素添加一个
dropzone
属性,这一步也不是必须的,可以省略。 - 在拖拽元素的
dragstart
中初始化相关的数据信息,主要是DataTransfer
对象。 - 在目标元素的
dragover
事件中,取消其默认操作。 - 在目标元素的
drop
事件中,处理接受到的数据。 - 在被拖拽元素的
dragend
事件中,做善后工作。若没有则可以省略。
大致代码如下:
<div id="source" draggable="draggable">source</div> <div id="target">target</div> <script type="text/javascript"> var target = document.getElementById('target'); var source = document.getElementById('source'); source.ondragstart = function(e){ e.dataTransfer.effectAllowed = 'copyMove'; e.dataTransfer.setData('test', 'testData'); }; target.ondragover = function(e){ e.dataTransfer.dropEffect = 'move'; e.preventDefault(); // 不能少 }; target.ondrop = function(e){ var elem = document.createElement('a'); elem.innerHTML = e.dataTransfer.getData('test'); e.target.appendChild(elem); }; </script>
draggable属性
draggable是一个枚举属性,用于指定一个标签是否可以被拖拽。有以下四种取值:
true
:表示此元素可拖拽。 false
:表示此元素不可拖拽。 auto
:除img
和带href
的标签a
标签表示可拖拽外,其它标签均表示不可拖拽。 - 其它任何值:表示不可拖拽。
dropzone属性
这个属性用于接受拖拽元素的目标元素上,表示能接受的数据类型及操作方式。多个值用空格分开,不区分大小写。其值有以下类型组成:
- copy:表示将允许的元素放到该元素上时,会将拖拽数据复制到目标元素上。
- link:表示将允许的元素放到该元素上时,将链接数据到目标元素上。
- move:表示将允许的元素放到该元素上时,会将数据移动到目标元素上。
- 以
string:
开头的字符串,长度不能小于8个字符:表示能接受DataTransferItem.kind
值为string
的data
对象。 - 以
file:
开头的字符串,长度不能小于6个字符:表示能接受DataTransferItem.kind
值为file
且DataTransferItem.type
的值匹配file:
之后的字符的DataTransferItem
的对象。
相关的事件
DragEvent接口定义
DragEvent
从MouseEvent
接口继承,其定义如下,与MouseEvent
相比,只是多了个DataTransfer
对象。所有针对拖拽的操作也是通过控制此对象来完成的。
[Construct(DOMString type, optional DragEventInit eventInitDict)] interface DragEvent : MouseEvent { readonly attribute DataTransfer? dataTransfer; }; /* 这是用于初始事件的参数定义 */ dictionary DragEventInit : EventInit { // 从UIEvent继承的属性: Window? view = null; long detail = 0; // 从MouseEvent继承的属性: long screenX = 0; long screenY = 0; long clientX = 0; long clientY = 0; boolean ctrlKey = false; boolean shiftKey = false; boolean altKey = false; boolean metaKey = false; unsigned short button = 0; unsigned short buttons = 0; EventTarget? relatedTarget = null; // DragEvent添加的新属性: DataTransfer? dataTransfer; }
事件描述
拖拽相关事件 事件名称 | 事件目标 | 可撤消? | 存储模式1 | dropEffect值 | 默认操作 | 备注 |
1.存储模式是针对于DataTransfer 对象的操作,具体数据见后表。 |
dragstart | 被拖拽元素 | 是 | 读、写 | none | 初始化操作 | 若调用preventDefault()函数取消此事件的默认行为,则拖拽功能将被取消。 |
drag | 被拖拽元素 | 是 | 保护模式 | none | | 在dragstart之后,释放鼠标之前,不管鼠标是否移动,此事件不停地被触发。 |
dragenter | 目标元素 | 是 | 保护模式 | effectAllowed限定的值。 | 更换目标元素。 | 进入目标元素时,触发一次。 |
dragleave | 离开前的目标元素 | 否 | 保护模式 | none | | 离开时触发一次。 |
dragover | 目标元素 | 是 | 保护模式 | effectAllowed限定的值 | 重置dropEffect为none ,并中断后续事件执行。 | 在dragenter之后,dragleave之前,不管是否移动,此事件都将不停地触发。 |
drop | 目标元素 | 是 | 只读模式 | 当前设定的值 | | 释放鼠后,由目标元素触发。 |
dragend | 被拖拽元素 | 否 | 保护模式 | 当前设定的值 | | 释放鼠标后,由被拖拽元素触发,顺序在drop之后。 |
目标元素是指当前鼠停留的元素,如要将A元素拖放到F元素上,中间经过的所有元素,在鼠标经过期间都是一个目标素,相应的事件都会被触发,A元素本身就是第一个目标元素。
DataTransfer接口
在HTML5中,为了实现在拖放过程中的数据交换,给所有的拖拽事件提供了一个DataTransfer
属性。通过此对象的方法和属性来完善拖放功能。
interface DataTransfer { attribute DOMString dropEffect; attribute DOMString effectAllowed; void setDragImage(Element image, long x, long y); readonly attribute DOMString[] types; DOMString getData(DOMString format); void setData(DOMString format, DOMString data); void clearData(optional DOMString format); readonly attribute DataTransferItemList items; readonly attribute FileList files; }
effectAllowed和dropEffect
这两个属性用于描述在拖拽过程中,鼠标显示的样式,受浏览器和操作系统的影响,鼠标显示的图标并不一致。
effectAllowed
表示此次拖拽允许显示的鼠标样式,可以是以下值:none
、copy
、copyLink
、copyMove
、link
、linkMove
、move
、all
和uninitialized
。只能在dragstart
事件中更改此值。
dropEffect
表示此次拖拽过程中显示的样式,可以是以下几个值:copy
、move
、link
和none
。在具体的拖拽过程中,还受effectAllowed
值限定,具体限定内容见下表,当dropEffect
的值被设置为一个不属于effectAllowed
限定的值时,整个事件链将被中止,即后续事件都将不会被触发,但不会发生任何错误提示。
effectAllowed与dropEffect对照表 effectAllowed | dropEffect |
1:根据用户所使用的平台不同,可能会出现的值,如在windows下,copyMove的effectAllowed值,默认为copy操作,在按shift键时,则会变成move操作。 |
none | none |
copy | copy |
copyLink | copy或是link1 |
copyMove | copy或是move1 |
all | copy、link1或是move1 |
link | link |
linkMove | link或是move1 |
move | move |
uninitialized,被拖拽为一个文本框中选中的内容? | move或是copy1,link1 |
uninitialized,被拖拽对象为一个普通选中项? | copy或是link1,move1 |
uninitialized,被拖拽对象为一个带链接的a元素 | link或是copy1,move1 |
其它情况 | copy或是link1,move1 |
setDragImage(image, x, y)
这个函数用于设置鼠标移动过程中随鼠标一起移动的效果图,而不是鼠标指针的显示效果。x
、y
参数用于指定图像相对于鼠标指针的位置;image
参数用于指定图像元素,若是一个img
元素,则显示图像元素,否则将给定的元素转换成一张图像并显示。
该函数只能在读写模式(也就是dragstart
事件)下有用,在其它事件中调用无效。若不调用此函数,则在拖拽时,被拖拽元素被转换成一个图处并当作一个效果图显示。
items属性
对items
的接口定义如下:
interface DataTransferItemList { readonly attribute unsigned long length; getter DataTransferItem(unsigned long index); // items[index] deleter void(unsigned long index); // delete items[index] void clear(); DataTransferItem? add(DOMString data, DOMString type); DataTransferItem? add(File data); } interface DataTransferItem { readonly attribute DOMString kind; readonly attribute DOMString type; void getAsString(FunctionStringCallback? _callback); File? getAsFile(); } [Callback, NoInterfaceObject] interface FunctionStringCallback { void handleEvent(DOMString data); }
从上面的定义不难看出:DataTransfer.items
就是DataTransferItem
的一个数组。DataTransferItemList
仅仅是定义一套以数组形式存取DataTransferItem
对象的接口。我们主要看一下DataTransferItem
类的定义:
- kind:表示数据的类型,只能是
string
或File
。单从字面就很好理解这两个值代表的是什么意思。 - type:实际数据的类型或是格式,一般用mimetype表示,但并不是强制mimetype格式。
- getAsString(callback):当
kind
属性为string
时,在只读或是读写模式下,可以通过回调函数处理此对象关联的实际数据。 - getAsFile():当
kind
为file
是,通过此函数能获取真实的数据,否则返回null
,只在只读或是读写模式下有效。
在非读写模式下删除DataTransferItemList
中的数据,会返回InvalidStateError
错误。若是在非读写模式下添加数据,则不执行任何操作。DataTransfer.setData
则是对这两个函数的封装(根据第二个参数决定是删除还是添加)。
types属性
返回根据下列步骤产生的字符串集合(DOMStringList
):
- 产生一个空的
DOMStringList
对象L。 - 遍历
DataTransfer.items
对象。 - 若
DataTransfer.items
的子项的kind
的值为string
,则将该项的type
值添加到L对象中。 - 若
DataTransfer.items
的子项的kind
的值为file
,则向L对象添加"Files"字符串。 - 返回L对象
getData(format)
getData
是从DataTransfer.items
中查找数据。返回符合以下条件的数据:
DataTransferItem.kind
为string
DataTransferItem.type
的值等于format
参数
如果没有找到匹配的或是处于保护模式下,则返回一个空字符串。
参数format
在传递到函数内部之前,都会被转换成小写字符,且如果参数值为text
或是url
,则会被转换成text/plain
和text/uri-list
。
setData(format, data)
setData
用于向DataTransfer.items
中添加或删除一条数据:
当没有指定第二个参数data
时,则是从DataTransfer.items
中删除符合以下条件的数据:
kind
等于string
type
等于参数format
当指定第二个参数data
时,则是向DataTransfer.items
中添加数据,新添加的数据格式如下:
kind
的值为string
type
的值为format
data
参数作为DataTransferItem
的实际值。
参数format
在传递到函数内部之前,都会被转换成小写字符,且如果参数值为text
或是url
,则会被转换成text/plain
和text/uri-list
。
如果不处于读写模式下,则不做任何操作。
clearData()
清除所有kind
值为string
的项。只在读写模式下起作用。
</section> 存储模式
存储模式决定了DataTransfer
各项内容是否可用。下表列出相关的信息,其中Y
表示可用,N
表示不可用。
存储模式与DataTransfer
各项的关系 | 读写 | 只读 | 保护 |
dropEffect | 只在dragenter 与dragover 事件中可更改,其它事件中只可读取。 |
effectAllowed | 只在dragstart 事件中起作用 |
items | 对items的操作详细情况参考后面的setData 函数 |
types | 仅在dragenter 、dragover 与drop 三个事件中可获取此值 |
setData | Y | N | N |
getData | Y | Y | N |
clearData | Y | N | N |
DataTransferItem.getAsString | Y | Y | N |
DataTransferItem.getAsFile | Y | Y | N |
来自:http://blog.830725.com/post/html5-drag-and-drop-intro.html