说说如何使用 HTML5 实现拖放功能(使用原生 API)

拖放指的是在框架间、窗口间或者应用间拖放网页元素。

1 拖放事件

拖放事件分为两种:被拖动的元素上触发的事件以及放置目标上触发的事件。拖动某元素时,将依次触发以下事件:

  1. dragstart
  2. drag
  3. dragend

按下鼠标键并开始移动鼠标时,在被拖动的元素上触发 dragstart 事件。光标变为不能放的符号(因为不能拖放到自己身上)。

在元素被拖动期间会持续触发 drag 事件。这与 mousemove 事件相似,鼠标移动的过程中,mousemove 事件也会持续触发。当拖动停止时(无论放置有效还是无效),会触发 dragend 事件。

默认情况下,不会在拖动期间改变被拖动元素的外观,但可以自定义修改。但大多数浏览器会为被拖动的元素创建一个半透明的副本,它会始终跟着光标移动。

当元素被拖动到一个有效的放置目标时,将依次触发以下事件:

  1. dragenter
  2. dragover
  3. dragleave 或 drop

被拖动的元素如果还在放置目标的范围内移动时,会持续触发 dragover 事件。如果元素被拖出了放置目标,将触发 dragleave 事件。如果元素被放置到了目标中,就会触发 drop 事件。这三个事件的目标都是作为放置目标的元素。

2 自定义放置目标

拖动元素到某个无效的放置目标时,会出现不可放置的符号(圆圈中的一条反斜线),表示不可放置。有些元素默认是不可放置的。可以重写这些元素的 dragenter 和 dragover 事件的默认行为,这样就可以把任何元素变为有效的放置目标。假设在页面上有一个 id 为 “droptarget” 的 <div> 元素,我们这样让它变为有效的放置目标:

var droptarget = document.getElementById("droptarget");

EventUtil.addHandler(droptarget, "dragover", function(event){
    EventUtil.preventDefault(event);
});
EventUtil.addHandler(droptarget, "dragenter", function(event){
    EventUtil.preventDefault(event);
});

在 Firefox 3.5+ 中,放置事件的默认行为是打开被放到放置目标的 URL,即如果放置的是图像,则会打开图像文件;如果是文本,就会报错。所以在 Firefox 中还要取消 drop 事件的默认行为:

EventUtil.addHandler(droptarget, "drop", function(event){
    EventUtil.preventDefault(event);
});

3 dataTransfer 对象

dataTransfer 对象让被拖动的元素向放置目标传递数据(字符串格式),因为它是事件对象的属性,所以只能在拖放的事件处理程序中使用 dataTransfer 对象。

它有两个方法,getData() 和 setData(),即获取和设置数据。,setData() 有一个参数,即要保存的数据类型(字符串格式),而 getData() 的第一个参数也是要保存的数据类型:

//设置和接收文本数据
event.dataTransfer.setData("text","some text");
var text = event.dataTransfer.getData("text");

//设置和接收 URL
event.dataTransfer.setData("URL","http://xxx");
var url = event.dataTransfer.getData("URL");

HTML5 可以指定各种的 MIME 类型,它也支持 “text” 和 “URL”,这两种类型会被分别映射为 “text/plain” 和 “text/uri-list”。

注意:保存在 dataTransfer 对象中的数据只能在 drop 的事件处理程序中读取,在 drop 的事件处理程序之外的地方,dataTransfer 对象就会被销毁!

拖动文本框中的文本时,浏览器会调用 setData() 方法,把拖动的文本以 “text” 格式保存在 dataTransfer 对象中。在拖放链接或者图像时,也会调用 setData() 并保存它们的 URL 地址。所以当这些元素被拖放到放置目标时,就可以使用 getData() 读取数据。也可以在 dragstart 事件中使用 setData() 自定义需要传递的数据。

数据的 URL 格式与文本格式不同。URL 格式的数据如果放置到另一个浏览器窗口中,就会打开这个 URL!

旧版的 Firefox不能正确处理 “url” 和 “text”,所在跨浏览器的方案是这样的:

var dataTransfer = event.dataTransfer;

//读取 URL
var url = dataTransfer.getData("url") || dataTransfer.getData("text/uri-list");

//读取文本
var text = dataTransfer.getData("Text");

这里把短字符的数据类型放在前面,因为 IE10 及之前版本还不支持扩展的 MIME 类型名!

4 dropEffect 和 effectAllowed

dropEffect 属性说明被拖动的元素能够执行哪一种放置行为:

属性值说明
none不能放置,除文本框之外的所有元素都是这个默认值。
move被拖动的元素可以移动到放置目标。
copy被拖动的元素可以拷贝到放置目标。
link放置目标会打开被拖动的元素的 URL 地址,所以被拖动的元素必须是一个链接。

上面的每一个值都会导致光标显示不同的符号,但实际上没有实现这些功能!所以我们要自己来实现它们!还有,必须在 ondragenter 事件中对放置目标应用 dropEffect 属性。

effectAllowed 属性表示允许拖动元素的哪一种 dropEffect 属性,所以这两个属性必须配合使用:

属性值说明
uninitialized被拖动的元素没有设置任何放置行为。
none被拖动的元素不能有任何行为。
copy只允许 “copy” 的 dropEffect 属性。
link只允许 “link” 的 dropEffect 属性。
move只允许 “move” 的 dropEffect 属性。
copyLink允许 “copy” 和 “link” 的 dropEffect 属性。
copyMove允许 “copy” 和 “move” 的 dropEffect 属性。
linkMove允许 “link” 和 “move” 的 dropEffect 属性。
all允许任意的 dropEffect 属性。

还有,必须在 ondragenter 事件中设置 effectAllowed 属性。

假设要把文本框中的文本拖放到一个 <div> 中,就必须把 dropEffect 和 effectAllowed 设置为 “move”。然后重写这个 <div> 的默认行为,写代码把文本插入到这个 <div> 中,这样拖放动作完成咯。


注意: Firefox 5 及之前的版本中的 effectAllowed 属性有 bug,所以如果在代码中设置了 effectAllowed 属性,可能不会触发 drop 事件!


5 可拖动

默认情况情况下,图像、链接和文本都是可拖动的。其中只有文本必须是在选中的情况下才可拖动!

HTML5 中的所有元素都有一个 draggable 属性,图像、链接中的这个属性是 true,所以是可拖动的。其他属性只要设置了这个属性就可以被拖动。

支持 draggable 属性的浏览器有这些:IE 10+、Firefox 4+、Safari 5+ 和 Chrome。Opera 11.5 及之前的版本都不支持这个属性。


注意: IE9 及更早的版本,是通过在 mousedown 事件中调用 dragDrop() 的方式,让所有的元素变为可拖动的。Safari 4 及之前的版本,是通过给元素设置 CSS 样式(-khtml-user-drag: element)的方式,让所有的元素变为可拖动的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值