HTML5原生拖放实例分析
HTML5提供了原生拖放功能的JavaScript API,使用起来很方便。
兼容性:

对于PC端浏览器,Firefox、Chrome、Safari支持良好,而IE和Edge浏览器有些特性不支持,如IE10和IE11、Edge对于dataTransfer.setData(format,data) ,只定义了"text"和"URL"两种有效的数据类型。而HTML5规范允许支持各种MIME类型。
详细参考这里:http://caniuse.com/#search=drag
本文实现HTML5原生拖放的应用Demo,用到了常用的方法和属性,兼容现代浏览器,还是先看效果:
下面详细介绍——
原生拖放事件:
应用于被拖动元素的事件:
- dragstart
 
按下鼠标并开始移动鼠标,会在被拖放的元素上触发dragstart事件。
注意:要使用HTML5的原生拖放功能,使该元素可拖动,需要设置draggable属性。默认情况下,图像、链接和被选中的文本是可以拖动的,因为它们的draggable属性已经自动被设置成true。
    
- drag
 
触发dragstart事件后,随即会触发drag事件,而且在元素被拖动期间会持续触发该事件。
- dragend
 
拖动停止(放开鼠标)的时候,会触发dragend事件。
应用于放置目标的事件:
- dragenter
 
只要有元素被拖动到放置目标上,就会触发dragenter事件。
- dragover
 
触发dragenter事件后,随即会触发dragover事件,而且只要被拖动元素在放置目标的范围内移动时,就会持续触发。
- dragleave
 
元素被拖出了放置目标,dragover事件不再发生,但会触发dragleave事件。
- drop
 
元素被放到了放置目标中,则会触发drop事件,而不是dragleave事件。
注意:(1)被拖动元素和放置目标可以设置为同一个元素,在自身上也可以触发drop事件,虽然好像没啥用 =。=
(2)被拖动元素进入放置目标范围和离开的参考标准是鼠标的位置,而不是鼠标下面拖动着的图像的边界
(3)拖动时显示在鼠标光标下方的图像,默认是该元素的一个副本,在dragstart事件中对完成对元素的复制(也可以通过setDragImage()自定义鼠标下拖动的元素),因此要隐藏本来的元素,最好在drag事件中处理,就是在复制后进行处理(参见文末的源代码)
dataTransfer对象
dataTransfer对象是事件对象的一个属性,只能在拖放事件的事件处理程序中访问。而且,dataTransfer对象的一些方法和属性也只能在特定的拖放事件中进行设置。
常用方法:
- setData(format,data)
 
在dragstart事件中,针对被拖放元素调用setData()函数,设置要传递的数据;用于从被拖放元素向放置目标传递字符串格式的数据。
第一个参数是数据类型,其中IE只定义了"text"和"URL"两种有效的数据类型;第二个参数是字符串,表示要传递的数据。
- getData(format)
 
在drop事件中,针对放置目标调用getData()函数,取得传递过来的数据。
第一个参数是setData( )中设置的数据类型
- setDragImage(element, x, y)
 
指定一副图像,当拖动发生的时候,显示在光标的下方。接受3个参数: 要显示的HTML元素和光标在图像中的x,y坐标。其中HTML元素可以是一幅图像,也可以是其他元素。
该属性IE10、IE11、Edge浏览器不支持。
- clearData(format)
 
清除以特定格式保存的数据。
常用属性:
- dropEffect
 
在dragenter事件中处理程序中,针对放置目标设置dropEffect属性的值,决定被拖动的元素能够执行哪种放置行为(同时被拖动元素拖到放置目标上时,会显示不一样的光标符号)
none:不能把拖动的元素放在这里。这是除了文本框之外所有元素默认的值。
move:应该把拖动的元素移动到放置目标。
copy:应该把拖动的元素复制到放置目标。
link:放置目标会打开拖动的元素(但拖动的元素必须是个链接,有URL地址)。
- effectAllowed
 
在dragstart事件处理程序中,针对被拖放元素设置effectAllowed属性的值,表示允许拖动元素的哪种dropEffect,和上面的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。
关于dataTransfer其他的一些方法和属性,以及更详细的介绍,请看这里https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API
文末源码部分——
HTML代码:
<div id='container'>
<div id='wrap'>
<img src="http://d3.freep.cn/3tb_160909012718ljdh572240.jpg" title='鞋子'/>
<img src="http://d2.freep.cn/3tb_160909012718973d572240.jpg" title='包子'/>
<img src="http://d2.freep.cn/3tb_1609090127197ux5572240.jpg" title='薯片'/>
</div>
<div id='cart'></div>
</div>
CSS代码:
*{
    margin:;
    padding:;
}
body{
    -webkit-user-select: none;
       -moz-user-select: none;
       -ms-user-select: none;
       user-select: none;
}
#wrap{
    height: 100px;
    text-align: center;
}
img{
    width: 100px;
    height: 100px;
    cursor: -webkit-grab;
    cursor: -moz-grab;
    cursor: grab;
}
#cart{
    width: 500px;
    height: 100px;
    border-radius: 20px;
    margin: 50px auto 0;
    background-color: orange;
}
#cart.hover{
    background-color: red;
}
#cart img{
    width: 70px;
    height: 70px;
    margin: 15px;
}
JS代码:
//被拖动元素的三个事件
function dragstart(e){
e = EventUtil.getEvent(e);
var target = EventUtil.getTarget(e);
e.dataTransfer.setData("text",target.title);
//因为IE10、IE11和Edge不支持setDragImage()方法,需要判断
if(e.dataTransfer.setDragImage){
e.dataTransfer.setDragImage(target,50,50);
} //effectAllowed事件和dropEffect事件搭配使用
e.dataTransfer.effectAllowed = 'move';
dragElement = target;
}
function drag(e){
e = EventUtil.getEvent(e);
var target = EventUtil.getTarget(e);
setOpacity(target,0);
}
function dragend(e){
e = EventUtil.getEvent(e);
var target = EventUtil.getTarget(e);
setOpacity(target,1);
} //放置目标的四个事件
function dragenter(e){
e = EventUtil.getEvent(e);
var target = EventUtil.getTarget(e);
//重要!重写dragenter事件的默认行为,使其可以触发drop事件
EventUtil.preventDefault(e);
//dropEffect事件和effectAllowed事件搭配使用
e.dataTransfer.dropEffect = 'move';
target.className = 'hover';
}
function dragover(e){
e = EventUtil.getEvent(e);
//重要!重写dragover事件的默认行为,使其可以触发drop事件
EventUtil.preventDefault(e);
}
function dragleave(e){
e = EventUtil.getEvent(e);
var target = EventUtil.getTarget(e);
target.className = '';
}
function drop(e){
e = EventUtil.getEvent(e);
var target = EventUtil.getTarget(e);
var title = e.dataTransfer.getData("text");
console.warn('把%s添加到购物车中!',title);
target.className = '';
dragElement.parentNode.removeChild(dragElement);
var img = dragElement.cloneNode();
img.draggable = false;
setOpacity(img,1);
cart.appendChild(img); //重要!为了让Firefox支持正常的拖放,取消drop事件的默认行为
EventUtil.preventDefault(e);
} //设置透明度
function setOpacity(element,value){
if(typeof element.style.opacity!='undefined'){
element.style.opacity=value;
}else{
element.style.filter = "alpha(opacity="+value*100+")";
}
}
//事件处理,做兼容处理
var EventUtil={
//添加事件处理程序
addHandler:function(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);
}else if(element.attachEvent){
element.attachEvent("on"+type,handler);
}else{
element["on"+type]=handler;
}
},
//获取事件对象
getEvent:function(event){
return event?event:window.event;
},
//获取事件的目标
getTarget:function(event){
return event.target||event.srcElement;
},
//取消默认事件
preventDefault:function(event){
if(event.preventDefault){
event.preventDefault();
}else{
event.returnValue=false;
}
}
}; var imgs = document.getElementsByTagName("img"),
cart = document.getElementById('cart'),
dragElement = null; for(var i=0; i<imgs.length; i++ ){
EventUtil.addHandler(imgs[i],'dragstart',dragstart);
EventUtil.addHandler(imgs[i],'drag',drag);
EventUtil.addHandler(imgs[i],'dragend',dragend);
}
EventUtil.addHandler(cart,'dragenter',dragenter);
EventUtil.addHandler(cart,'dragover',dragover);
EventUtil.addHandler(cart,'dragleave',dragleave);
EventUtil.addHandler(cart,'drop',drop);
参考资料: 《JavaScript高级程序设计》,MDN
HTML5原生拖放实例分析的更多相关文章
- HTML5 原生拖放
		
前言: HTML5提供专门的拖拽与拖放的API,可以方便的指定某个元素可拖动,可以创建自定义的可拖动元素和放置目标 相关知识点: 1.拖放事件 拖放元素时,将依次触发下列事件 dragstart 按 ...
 - C#保留2位小数几种场景总结    游标遍历所有数据库循环执行修改数据库的sql命令    原生js轮盘抽奖实例分析(幸运大转盘抽奖)  javascript中的typeof和类型判断
		
C#保留2位小数几种场景总结 场景1: C#保留2位小数,.ToString("f2")确实可以,但是如果这个数字本来就小数点后面三位比如1.253,那么转化之后就会变成1.2 ...
 - 当里个当,免费的HTML5连载来了《HTML5网页开发实例详解》连载(一)
		
读懂<HTML5网页开发实例详解>这本书 你还在用Flash嘛?帮主早不用了 乔布斯生前在公开信“Flash之我见”中预言:像HTML 5这样在移动时代中创立的新标准,将会在移动设备上获得 ...
 - HTML5 之拖放(drag与drop)
		
拖放(Drag 和 drop)是 HTML5 标准的组成部分. 拖放是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. HTML5 拖放实例 ...
 - 深入理解javascript原生拖放
		
× 目录 [1]拖放源 [2]拖放目标 [3]dataTransfer对象[4]改变光标 前面的话 拖放(drag-and-drop,DnD)其实是两个动作——拖和放.所以,它涉及到两个元素.一个是被 ...
 - 《HTML5与CSS3实例教程》
		
<HTML5与CSS3实例教程> 基本信息 作者: (美)Brian P. Hogan 译者: 卢俊祥 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:97871153634 ...
 - nodejs的模块系统(实例分析exprots和module.exprots)
		
前言:工欲善其事,必先利其器.模块系统是nodejs组织管理代码的利器也是调用第三方代码的途径,本文将详细讲解nodejs的模块系统.在文章最后实例分析一下exprots和module.exprots ...
 - HTML5 总结-拖放-3
		
HTML5 拖放 拖放(Drag 和 drop)是 HTML5 标准的组成部分. 拖放 拖放是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放 ...
 - 《JAVASCRIPT高级程序设计》原生拖放和媒体元素
		
一.原生拖放 最早在网页中引入javascript拖放功能的是IE4,当时,网页中只有两种对象可以拖放:图像和某些文本.而现在,几乎网页中的任何元素都可以拖放以及作为放置目标.下面介绍一些与拖放相关的 ...
 
随机推荐
- Codeforces Round #237 (Div. 2) C. Restore Graph(水构造)
			
题目大意 一个含有 n 个顶点的无向图,顶点编号为 1~n.给出一个距离数组:d[i] 表示顶点 i 距离图中某个定点的最短距离.这个图有个限制:每个点的度不能超过 k 现在,请构造一个这样的无向图, ...
 - ZOJ 2112 Dynamic Rankings(动态区间第 k 大+块状链表)
			
题目大意 给定一个数列,编号从 1 到 n,现在有 m 个操作,操作分两类: 1. 修改数列中某个位置的数的值为 val 2. 询问 [L, R] 这个区间中第 k 大的是多少 n<=50,00 ...
 - DSP中CMD文件
			
DSP中CMD文件 (2012-12-26 20:54:17) 转载▼ 标签: 杂谈 分类: DSP FPGA DSP的存储器的地址范围,CMD是主要是根据那个来编的.CMD 它是用来分配rom和ra ...
 - Qt 添加资源文件
			
*本人乃小白,博文主要用于个人记录,不保证内容准确无误* 我们编写的gui可能需要一些额外的资源(比如贴图用的图片),可用资源文件统一管理.以下以图片为例. 用qt creator 打开工程,为工程新 ...
 - MSSQL大数据量增加字段耗时对比
			
单个数据表记录数为1亿4千万条. 一.测试同时增加两个允许为空的字段. ALTER TABLE [dbo].[XRecord] ADD [sType] int,[cType] int GO 开始时间: ...
 - 个人对joomla3.2x和joomla2.5X浅薄看法
			
很久没有写joomla文章了,发现想写的东西还是挺多的,后面抽时间补回来,其实更多还是php的一些东西.joomla3.0以后系统改变挺大,后台都是用bootstrap作为主题,个人对这个无爱,因为他 ...
 - JS思维之路菜鸟也能有大能量(2)--模拟数组合并concat
			
我们有两个这样的数组 var arr1 = [1,2,3]; var arr2 = [4,5,6]; 任务:合并成这样,请至少提供两种思路. var arr1 = [1,2,3,4,5,6]; 思路一 ...
 - 【Head-First设计模式】C#版-学习笔记-开篇及文章目录
			
原文地址:[Head-First设计模式]C#版-学习笔记-开篇及文章目录 最近一年断断续续的在看技术书,但是回想看的内容,就忘了书上讲的是什么东西了,为了记住那些看过的东西,最好的办法就是敲代码验证 ...
 - java中getBytes方法可能使图片文件产生的问题
			
InputStream is = new FileInputStream(fl); ImageInputStream iis = ImageIO.createImageInputStream(is); ...
 - 网络通信分享(一):数字签名,数字证书,https通信,数据加密
			
加密算法: 一:对称加密算法 在对称加密算法中,加密使用的密钥和解密使用的密钥是相同的.也就是说,加密和解密都是使用的同一个密钥.因此对称加密算法要保证安全性的话,密钥要做好保密,只能让使用的人知道, ...