Html 5 drag and drop 简介

HTML5提供了专门拖拽和拖放的API

draggable属性 启用拖拽

draggable属性是否可被拖拽, 可选值: true, false, auto

<div draggable="true" title="can drag me">可以被拖拽哦</div>
  1. 为触发拖拽的元素添加 draggable="true" 特性,用于启动HTML5的DnD功能(即元素的 dragstart 事件可被触发);

  2. 在FF下即使添加 draggable="true" 特性,但仅仅会触发 dragstart 事件,但DnD功能并没有被完全打开(拖拽元素时没有任何视觉效果),需要调用 event.dataTransfer.setData('Text','') 彻底开启DnD功能。

  3. 在Safari4下则需要借助CSS规则来启动DnD功能, [draggable=true]{ -webkit-user-drag: element; }

拖拽事件

被拖拽元素的生命周期

  • dragstart 元素开始被拖拽时触发

    1. event.dataTransfer的大部分设置均在这里配置
    2. 若调用event.preventDefault()则会阻止拖拽行为,导致后续的拖拽事件不被触发
    3. 触发dragstart事件后,其他元素的mousemove,mouseover,mouseenter,mouseleave,mouseout事件均不会被触发了
  • drag 元素被拖拽中触发

  • dragend 拖拽完成后触发

目标元素的生命周期

  • dragenter 拖拽元素进入目标元素时触发, event.target为目标元素

  • dragover 拖拽元素在目标元素上移动时触发 , event.target为目标元素

    1. 可以在这里设置dropEffect的值,事件的默认行为是将dropEffect设置为none
    2. 该事件是被拖拽元素在目标元素上移动一段时间后才触发
    3. 事件的默认行为是不允许被拖拽元素在其他元素上释放或放置(即无法触发 drop 事件),需要通过 event.preventDefault() 来阻止默认行为才能触发后续的 drop 事件。
  • dragleave 拖拽元素离开目标元素时触发, event.target为目标元素.

  • drop 拖拽元素到目标元素上并释放鼠标, event.target为目标元素

    1. 对于外来的被拖拽元素(超链接、文件、图片源), drop 事件的默认行为是浏览器将当前页面重定向到被拖拽元素所指向的资源上
    2. 对文档内部的被拖拽元素,IE10+和Chrome下的默认行为是不作为,而FF得默认行为是新打开一个文档用于访问被拖拽元素所指向的资源

整体生命周期

dragstart -> drag -> dragenter -> dragover -> <dragleave> -> drop -> dragend

DataTransfer对象

DataTransfer对象用于在配置拖拽行为效果,并且在拖拽过程的各事件间传递数据信息。它存储在事件对象当中.

属性

effectAlloweddropEffect 最主要的作用是,用于配置拖拽操作过程中鼠标指针的类型以便提示用户后续可执行怎样的操作;其次的作用是,控制 drop 事件的触发与否。

// dragstart事件中设置
// copy, link, move, copyLink, copyMove, linkMove, all, none
event.dataTransfer.effectAllow = 'move' // dragover事件中设置
// copy, link, move, none
event.dataTransfer.dropEffect = 'move';

方法

  • event.dataTransfer.addElement(element)

    添加一起跟随鼠标移动的元素。仅在 dragstart 事件中调用

  • event.dataTransfer.setDragImage(image, x, y);

    设置拖动时跟随鼠标移动的图片,用来替代默认的元素,若image不是图片元素则会元素临时转换为图片;x用于设置图标与鼠标在水平方向上的距离,y设置图标与鼠标在垂直方向上的距离。仅在 dragstart 事件中调用。IE10+不支持该方法;

  • event.dataTransfer.setData(format, data)

    将指定格式的数据赋值给dataTransfer或clipboardData,format值范围为URL、Text(或text)和各种MIME类型,其实Text会被自动映射为text/plain,URL会被自动映射为text/uri-list类型。仅在 dragstart 事件中调用。

  • event.dataTransfer.getData(format)

    从DataTransfer对象或ClipboardData对象中获取指定格式的数据

  • event.dataTransfer.clearData(format);

    从DataTransfer对象或ClipboardData对象中删除指定格式的数据。仅在 dragend 事件中调用,在其他事件中调用会抛InvalidStateError

数据存储模式

  • Read/Write mode: 在 dragstart 事件为该模式,可读写数据
  • Read-only mode: 在 drop 事件为该模式,仅能读取数据
  • Protected mode: 在其他事件为该模式,仅能枚举数据

特征检测是否支持HTML5的DnD API

var supportDnD = function() {
var div = document.createElement('div');
return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
};

实例

拖拽列表元素到左侧div,然后删除该列表元素

<div class="dustbin"><br />垃<br />圾<br />箱</div>
<div class="dragbox">
<div class="draglist" title="拖拽我" draggable="true">列表1</div>
<div class="draglist" title="拖拽我" draggable="true">列表2</div>
<div class="draglist" title="拖拽我" draggable="true">列表3</div>
<div class="draglist" title="拖拽我" draggable="true">列表6</div>
</div>
<div class="dragremind"></div> var eleDustbin = $(".dustbin")[0], eleDrags = $(".draglist"), lDrags = eleDrags.length, eleRemind = $(".dragremind")[0], eleDrag = null;
for (var i=0; i<lDrags; i+=1) {
eleDrags[i].onselectstart = function() {
return false;
};
eleDrags[i].ondragstart = function(ev) {
/*拖拽开始*/
//拖拽效果
ev.dataTransfer.effectAllowed = "move";
ev.dataTransfer.setData("text", ev.target.innerHTML);
ev.dataTransfer.setDragImage(ev.target, 0, 0);
eleDrag = ev.target;
return true;
};
eleDrags[i].ondragend = function(ev) {
/*拖拽结束*/
ev.dataTransfer.clearData("text");
eleDrag = null;
return false
};
}
eleDustbin.ondragover = function(ev) {
/*拖拽元素在目标元素头上移动的时候*/
ev.preventDefault();
return true;
}; eleDustbin.ondragenter = function(ev) {
/*拖拽元素进入目标元素头上的时候*/
this.style.color = "#ffffff";
return true;
};
eleDustbin.ondrop = function(ev) {
/*拖拽元素进入目标元素头上,同时鼠标松开的时候*/
if (eleDrag) {
eleRemind.innerHTML = '<strong>"' + eleDrag.innerHTML + '"</strong>被扔进了垃圾箱';
eleDrag.parentNode.removeChild(eleDrag);
}
this.style.color = "#000000";
return false;
};
05-06 08:48