拖拽的实现


12.5更新


拖拽

前端经常使用拖拽进行图片上传,那么拖拽是如何实现的呢?
使用拖拽基本过程如下:首先定义哪些元素是可拖动的,在鼠标左键点击一个可拖动元素进行拖拽;拖拽元素进行移动,拖拽元素的位置发生改变,可以通过绝对定位实现;鼠标释放拖拽元素。

HTML5实现

拖拽删除元素实例

1
2
<div id="main">垃圾桶</div>
<div id="test-drag" draggable="true">拖拽元素区域:拖拽到垃圾桶中删除</div>

Javascript代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
var dragElement = document.getElementById("test-drag");
var targetElement = document.getElementById("main");

//拖动对象操作
dragElement.ondragstart = function (event) {
console.log("开始拖拽");
event.dataTransfer.setData("deleteDiv", this.id);

};
dragElement.ondrag = function () {
console.log("拖动中");
};
dragElement.ondragend = function () {
console.log("拖动结束");
};


//目标对象操作
targetElement.ondragenter = function () {
console.log("拖拽对象进入");
};
targetElement.ondragleave = function () {
console.log("拖拽对象离开");
};

targetElement.ondragover = function (event) {
console.log("拖拽对象在目标对象上");
event.preventDefault(); //必须阻止默认事件,否则无法触发ondrop
};

targetElement.ondrop = function (event) {
console.log("拖拽对象松手释放在目标对象上");
var deleteDivId = event.dataTransfer.getData("deleteDiv"); //得到数据--id值
var deleteDiv = document.getElementById(deleteDivId); //根据id值找到相关的元素
deleteDiv.parentNode.removeChild(deleteDiv); //从父元素中删除子节点
};

API

可拖拽对象

通过设置draggable属性
draggabletrue 表明可拖拽
draggablefalse 表明元素不可拖拽
draggableauto 默认,只有img图片,a链接,input文字选中三种情况可拖拽

拖拽对象API

dragstart:可拖拽元素拖拽开始时触发
drag:可拖拽元素拖拽触发
dragend:可拖拽元素拖拽结束时触发

目标对象API

dragenter:可拖拽元素进入目标放置区域触发
dragexit:可拖拽元素不再是拖动操作的直接选择目标。
dragleave:可拖拽元素离开目标放置区域触发
dragover:可拖拽元素在目标放置区域移动时触发
drop:可拖拽元素在目标放置区域放置时触发

注意:dragenterdragover事件的默认行为是不允许被拖拽元素在其他元素上释放或放置(即无法触发drop事件),需要通过 event.preventDefault()或者return false来阻止默认行为才能触发后续的drop事件。(实测只需要dragover事件阻止默认事件)

event.dataTransfer对象
属性

DataTransfer对象用于在配置拖拽行为效果,并且在拖拽过程的各事件间传递数据信息。它存储在事件对象当中,下面我们逐步了解它吧。

  1. [object DragEvent]对象
    继承自[object MouseEvent] 对象,其实就多了个{DataTransfer} dataTransfer属性
  2. [object DataTransfer]对象详解
    上文说到DataTransfer对象可用于传递数据信息,而数据信息的数据类型被限定为字符串和文件类型

    1. effectAlloweddropEffect属性
      这个两个属性对于初次接触DnD的朋友来说,可谓最令人摸不着头脑的,网上和各书籍上对这两个属性的解释均不全面,下面我试图尽量把它们讲明白
      effectAlloweddropEffect最主要的作用是,用于配置拖拽操作过程中鼠标指针的类型以便提示用户后续可执行怎样的操作;其次的作用是,控制 drop 事件的触发与否。

      1. effectAllowed
        作用:用于设置被拖拽元素可执行的操作。
        取值范围:
        copy ,限定dropEffect的属性值为copy,否则会鼠标指针为禁止样式
        link ,限定dropEffect的属性值为link,否则会鼠标指针为禁止样式
        move ,限定dropEffect的属性值为move,否则会鼠标指针为禁止样式
        copyLink ,限定dropEffect的属性值为copylink,否则会鼠标指针为禁止样式
        copyMove ,限定dropEffect的属性值为copymove,否则会鼠标指针为禁止样式
        linkMove ,限定dropEffect的属性值为linkmove,否则会鼠标指针为禁止样式
        all,允许dropEffect的属性值为任意值none,鼠标指针一直为禁止样式,不管dropEffect的属性值是什么
        uninitialized,没有限定dropEffect属性的值,效果和all一样。

        注意:仅能在dragstart事件中设置该属性,其他事件中设置均无效。

      2. dropEffect
        作用:用于设置目标元素将执行的操作,若属性值属于effectAllowed范围内,则鼠标指针将显示对应的指针样式,否则则显示禁止的指针样式。
        取值范围:
        copy:被拖拽元素将被复制到目标元素内,若属于effectAllowed范围内时,则鼠标指针显示复制的样式,否则则显示禁止的指针样式。
        link被拖拽元素将以超链接的形式打开资源(具体是否打开资源请参考七、2),若属于 effectAllowed范围内时,则鼠标指针显示超链接的样式,否则则显示禁止的指针样式。
        move:被拖拽元素将被移动到目标元素内,若属于effectAllowed范围内时,则鼠标指针显示移动的样式,否则则显示禁止的指针样式。
        none:被拖拽元素不能在目标元素上作任何操作,一直显示禁止的指针样式。除了文本框外其他元素的默认值均为none

      注意:

      1. 仅能在dragover事件中设置该属性值,其他事件中设置均无效
      2. 当显示禁止的指针样式时,将无法触发目标元素的 drop 事件。
方法
  1. DataTransfer.getData()
    获取DataTransfer对象中的一个数据
  2. DataTransfer.setData()
    DataTransfer对象中添加一个数据
  3. DataTransfer.clearData()
    DataTransfer对象中删除一个数据

拖拽过程

在上述实例中,我们使用HTML5 drapdrop实现了一个拖拽一个元素到指定区域中进行删除。HTML5新增drag事件以方便解决拖拽问题。
首先,在这个过程中我们要定义一个可拖拽元素,对拖拽添加属性draggable="true"即可定义该元素为可拖拽对象。
第二,在拖拽元素开始后,可以通过drag事件的dataTransfer对象进行数据的传递。可设置数据来传递文件等。在上述例子中event.dataTransfer.setData()传递被删除元素的ID。
第三,放置拖拽元素,通常情况下页面元素为不可放置拖拽元素区域。放置拖拽元素是通过对目标元素的drop事件实现,但是只有目标元素dragenterdragover的触发事件最后必须通过取消事件来防止默认处理,即为return false或阻止默认事件event.preventDefault(),则该目标元素才为可放置拖拽元素区域,drop事件才会被触发。否则不会触发drop事件。

JS实现

裁剪

预览

操作实例

参考文献

-HTML5魔法堂:全面理解Drag & Drop API