HTML5 原生拖放

发展

原生拖放的发展大致可分为三个阶段:IE4、IE5+、HTML5。

IE4 是最早在网页中引入 JavaScript 拖放功能的,当时只有图像和选中的文本可以拖放,并且只有文本框是有效的放置目标。
IE5 拖放功能进一步得到了扩展,添加了新的事件,几乎网页中的任何元素都可以作为放置目标。
IE5.5+ 又更进一步,让网页中的任何元素都可以拖放。
HTML5 在 IE 的实例基础上,进一步制定了拖放的规范。

Firefox 3.5+、Safari 3+、Chrome、Opera 12+也根据 HTML5 规范实现了原生拖放功能。

拖放事件

在进行拖放操作的不同阶段会触发数种事件。注意,在拖拽的时候只会触发拖拽的相关事件,鼠标事件,例如 mousemove,是不会触发的。当从操作系统拖拽文件到浏览器的时候,dragstart 和 dragend 事件不会触发。

拖动某元素时,依次触发以下事件

dragstart
当一个元素被拖拽的时候触发。

drag
触发 dragstart 后,随即会触发 drag 事件,而且在元素被拖动期间会持续触发该事件。

dragend
拖动停止时触发。(无论元素是放到了有效的放置目标还是无效的放置目标上)

元素拖放到有效的放置目标上时,依次触发以下事件

dragenter
元素被拖放到放置目标上触发。

dragover
被拖动的元素在放置目标范围内移动时,会持续触发该事件。

dragleave
元素被拖出了放置目标,触发该事件,并且 dragover 事件不再发生。

drop
元素被放到了放置目标中,触发该事件。

拖放步骤

  • 定义拖拽目标

  • 定义拖拽数据

  • (可选)设置拖动反馈图片

  • 设置拖动效果

  • 定义放置目标

  • 拖放后的逻辑处理

定义拖拽目标

默认情况下,图像、链接和已选中的文本是可以拖动的。文本需要被选中才能拖动,而图像和链接在任何时候都可以拖动。

让其他元素可拖动也是可以的。HTML5 为所有 HTML 元素规定了一个 draggable 属性,表示是否可以拖动。图像和链接的 draggable 属性自动被设置成了 true,其他元素是 false。

// 设置图像不可拖动
<img src="http://www.seiue.com" draggable="false">

// 设置这个元素可以拖动
<div draggable="false">可拖动的DIV</div>

支持 draggable 属性的浏览器有 IE 10+、Firefox 4+、Safari 5+、Chrome 和 Opera 12+。

定义拖拽数据

我们有时会需要在拖放操作时进行数据交换,IE 引入了 dataTransfer对象,它是事件对象的一个属性,用于从被拖动元素向放置目标传递数据。因为它是事件对象的属性,所以只能在拖放事件中访问,不能单独创建。目前,HTML5 规范也收入了 dataTransfer 对象。

实现数据交换主要用到两个方法:getData(type)setData(type, data)type表示保存的数据类型,取值为“text”或“URL”,getData() 通过 setData() 设置的 type 来取到保存的值。

function dragStart(e) {
    // 设置文本数据
    e.dataTransfer.setData('text', 'hello world');
    // 设置URL
    e.dataTransfer.setData('URL', 'www.seiue.com');
}

function drop(e) {
    // 接收文本数据
    var text = e.dataTransfer.getData('text');
    // 接收URL
    var url = e.dataTransfer.getData('URL');
}

drag.addEventListener('dragStart', dragEnter, false);
drop.addEventListener('drop', drop, false);

建议总是添加 text/plaintext/uri-list来替代textURL,因为后者存在兼容问题并且最终会被映射为前者。

设置拖动反馈图片

当发生一次拖拽时(dragstart 事件触发的元素),会在拖拽的元素处产生一个半透明的图片(该元素副本),并且会在拖拽过程中跟随鼠标移动,这就是反馈图片。这个图片是自动生成的,无需你亲自设定,但可以通过setDrawImage来自定义一个反馈图片。

setDrawImage是 dataTransfer 对象的一个方法。

event.dataTransfer.setDrawImage(image, xOffset, yOffset)

需要传入三个参数,分别是:一个图片的引用(可以是图片元素对象、canvas或其他元素对象),图像内的水平偏移量,图像内的垂直偏移量。下面的例子定义了一个反馈图片。

function dragCustomImage(e) {
  var img = document.createElement('img')
  img.setAttribute('src', 'drag-img.jpeg')

     e.dataTransfer.setDragImage(img, 150, 150)
}

设置拖动效果

dataTransfer 对象不光能够传输数据,还能通过它来确定被拖动元素以及防止目标元素能够接收什么操作。主要用到两个属性:dropEffecteffectAllowed

dropEffect

可以知道被拖动的元素能够执行哪种放置操作。这个属性有4个值。

  • none: 禁止把拖放的元素放在这里。

  • move: 可以把拖放的元素移动到放置目标。

  • copy: 可以把拖放的元素复制到放置目标。

  • link: 放置目标会打开拖动的元素(拖动的元素必须是一个链接,有URL)。

把元素拖放到放置目标时,以上的每个值都会导致光标显示不同的符号。每种操作触发什么样的行为需要你来自行实现,浏览器不会帮你移动、复制和打开链接。要使用 dropEffect,我们需要在 dragenter事件处理程序中设置它的属性。

effectAllowed

dropEffect 属性需要搭配 effectAllowed 属性才生效。effectAllowed 属性表示允许拖动元素的哪种 dropEffect。effectAllowed 有以下值。

  • none: 被拖动的元素不能有任何行为。

  • copy: 只允许值为”copy“的 dropEffect。

  • link: 只允许值为“link” 的 dropEffect。

  • move: 只允许值为“move”的 dropEffect。

  • copyLink: 允许值为“copy”和“link”的 dropEffect。

  • copyMove: 允许值为“copy”和“move”的 dropEffect。

  • linkMove: 允许值为“link”和“move“的 dropEffect。

  • all: 允许任意 dropEffect。

需要在dragstart事件处理程序中设置它的属性。

定义放置目标

所有元素都支持放置目标事件,但这些元素默认是不允许放置的。如果拖动的元素拖放到了不允许放置的元素,是不会触发drop 事件的。
把元素变成有效的放置目标,需要重写dragenterdragover事件的默认行为。

var dropTarget = document.getElementById('dropTarget');

dropTarget.addEventListener('dragenter', function(e) {
    e.preventDefault();
}, false);

dropTarget.addEventListener('dragover', function(e) {
    e.preventDefault();
}, false);

处理拖放后的做的事情

drop事件发生时做一些事情,你可能想要获取拖拽目标携带的数据并做某些相应的事情。

参考资料

    原文作者:马超mcc
    原文地址: https://segmentfault.com/a/1190000009265219
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞