这篇文章发布于 2011年02月9日,星期三,20:58,归类于 JS API。 阅读 448496 次, 今日 6 次 70 条评论
by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=1419
一、前面的话
HTML5提供专门的拖拽与拖放的API,以后实现这类效果就不必乱折腾了。但是,考虑到Opera浏览器似乎对此不感冒,在通用性上有待商榷,所以这里也就简单说一说。
二、相关重点
- DataTransfer 对象:退拽对象用来传递的媒介,使用一般为Event.dataTransfer。
- draggable 属性:就是标签元素要设置draggable=true,否则不会有效果,例如:
<div title="拖拽我" draggable="true">列表1</div>
- ondragstart 事件:当拖拽元素开始被拖拽的时候触发的事件,此事件作用在被拖曳元素上
- ondragenter 事件:当拖曳元素进入目标元素的时候触发的事件,此事件作用在目标元素上
- ondragover 事件:拖拽元素在目标元素上移动的时候触发的事件,此事件作用在目标元素上
- ondrop 事件:被拖拽的元素在目标元素上同时鼠标放开触发的事件,此事件作用在目标元素上
- ondragend 事件:当拖拽完成后触发的事件,此事件作用在被拖曳元素上
- Event.preventDefault() 方法:阻止默认的些事件方法等执行。在ondragover中一定要执行preventDefault(),否则ondrop事件不会被触发。另外,如果是从其他应用软件或是文件中拖东西进来,尤其是图片的时候,默认的动作是显示这个图片或是相关信息,并不是真的执行drop。此时需要用用document的ondragover事件把它直接干掉。
- Event.effectAllowed 属性:就是拖拽的效果。
三、相关实例
为了便于理解上面的粗体的事件啊对象啊什么的,做了个很简单的demo页面。
您可以狠狠地点击这里:HTML5 drag & drop删除元素demo
此demo实现的效果是把右侧的列表拖动到左侧的写着果敢的“垃圾箱”三个字的div层上,此列表元素就会从这个星球上消失。如下截图连环画所示:
源代码展示
其中HTML结构如下:
<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">列表4</div> <div class="draglist" title="拖拽我" draggable="true">列表5</div> <div class="draglist" title="拖拽我" draggable="true">列表6</div> </div> <div class="dragremind"></div>
JS代码如下:
var $ = function(selector) { /*简单的选择器方法*/ ... }; 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; };
四、匆匆结语
今天是年后第一天上班,没有多少想折腾的心情,所以,一些啰哩吧嗦的话就省了。虽然是HTML5的东西,但是,根据findmebyip中显示的浏览器支持情况来看,IE6~IE8都是有drag & drop API的(见下截图)。
根据自己的简单的测试,低版本的IE浏览器确实支持诸如ondragstart事件,但是会报不认识dataTransfer的错误。可见IE在细节的处理上与现代浏览器有些不同。但是,目前自己没有这么多精气神把IE下的拖拽也折腾出来,故请原谅目前demo在IE下是纹丝不动,没有效果也不报错的。回头有功夫,一定会把IE相关的些东西补上。
感谢阅读。文中要是有表述不准确的地方,欢迎指正。
本文为原创文章,会经常更新知识点,为了避免陈旧知识误导,转载请注明出处,方便溯源。
本文地址:http://www.zhangxinxu.com/wordpress/?p=1419
(本篇完)
- 基于HTML5 drag/drop模块拖动插入排序删除完整实例 (0.750)
- 微信网页悬浮窗交互效果的web实现 (0.607)
- 拖拽献祭中的黑山羊-DataTransfer对象 (0.390)
- CSS3&HTML5各浏览器支持情况一览表 (0.207)
- 实现兼容性的CSS粗虚线边框(dashed)效果 (0.170)
- HTML5终极备忘大全(图片版+文字版) (0.167)
- 翻译-你必须知道的28个HTML5特征、窍门和技术 (0.160)
- JavaScript实现最简单的拖拽效果 (0.130)
- 有意思:textarea resize属性下纯CSS交互效果 (0.130)
- 开源移动端元素拖拽惯性弹动以及下拉加载两个JS (0.130)
- 完善:HTML5表单新特征简介与举例 (RANDOM - 0.014)
大佬,拖动的时候,draggable=“true”, @dragstart=”dragStartFn”,为什么点击后不触发start?拖动元素层级也在最上层,不解
关键是触摸屏难拖动。
发现在 QQ 浏览器里不支持 drop 事件,旭哥有什么好的建议吗,谢谢 ~
在拖拽的过程中出现的禁用标志可以修改吗?可以修改成一个手势的标志吗?
膜拜
大神,ondragleave 呢?
刚遇到一个问题,vue框架
ondragleave 会再dragover的时候触发,
dragEvent 的offsetx,y 均在父盒子里面,
明明写的 ”The dragleave event is fired when a dragged element or text selection leaves a valid drop target.“
搞不懂为什么,望大神指教一二。
为什么手势无法拖放
旭哥 看了你很多的技术文章 受益匪浅 ; 今天来才发现你出书了 必须得买啊
感谢支持。
我也买了《CSS世界》,期待书!
大神,谷歌、火狐要把Http网站标记为不安全了
如果拖动的div下面有子节点,则在火狐浏览器无法拖动。子节点倒是能拖,怎么破?而且拖的时候松开就弹出新窗口,并没有用到setdata
有个问题,在windows下拖动会产生鼠标变成禁止图标的样式,在mac下是没问题的,这个有解决的办法吗。。
在dragenter里event.preventDefault(),然后就解决了
大神,拖拽后有什么方法刷新不改变状态呀?
2
如何兼容移动端
大神你好。我想请问一下我如何在drag过程中修改鼠标指针的样式?这个问题我查了好多地方大多用jqueryUI解决的。用的不是原生的drag事件。而我在项目里用的是原生的。而且用的是vue、
有个小bug。就是当被拖曳元素进入目标元素后,又出来,然后,目标元素上的颜色不会恢复。
我试了下,用ondragleave事件,把目标元素的颜色改回来就可以了
大神,ie的问题啥时候能补充啊?
chrome 53.0.2785.143 m 不能拖拽…
opera已经可以支持了
看完博主的这篇文章,自己操作了两遍,查看了很多资料,可能网上这方面的文章不是很有深度,没有找到自己满意的答案。一个是为什么每个事件后面都要加true,或者false;
第二是‘ondragover中一定要执行preventDefault(),否则ondrop事件不会被触发。‘这句话,我也通过代码证明了确实是需要阻止默认行为的,但是为什么呢?
ondragover执行preventDefault(),是因为默认情况下是无法将数据、元素放到其他元素中的,如果需要允许,就要阻止默认处理;
/*拖拽元素在目标元素头上移动的时候*/
eleDustbin.ondragover = function (ev) {
return false;
};
直接阻止默认行为
学习了,多谢博主
drag后打开新标签,怎么解决
试试看这个 event.stopPropagation()
这个貌似也没有用啊
我也发现了,的确拖一次,火狐就开个新标签…
http://www.cnblogs.com/strangerqt/p/6133708.html 参考这个地址 setData的key 别设置为 text
www_itcast_cn/news/20160520/1713344905.shtml
刚刚看到这个网站上也有,觉得很奇怪
看时间就可以了
在拖拽的时候出现的两个层.一个层消失,另一个在可视区域外部,但是鼠标到达要拖拽的地方,位置是正确的,想问下,让消失的出现,并跟随鼠标的位置移动,怎么设置
在 dragenter 与 dragover 事件中 return false 或者调用 event.preventDefault()(tips:因为拖放目标要通过取消事件来告知浏览器它对放置感兴趣)就可以在 IE , edge 等浏览器中拖放了
有什么办法能改变拖放效果呢?浏览器原生的有点生硬,拖放的元素还会在原来的位置上,随着鼠标移动会更自然吧,被拖放到上面的元素似乎也不能挪动。
测试了一下,<ie10以下都不支持这个功能。
火狐下会新开一个窗口是什么情况,其他还可以
我想说 您的这篇文章 我是真的没看懂,,我想 对我来说 这JS代码的学习量比较大,,,我更想知道 一个最简单的拖拽是怎么实现的。
最简单的拖拽您跑过来看这篇文章干嘛?
有一个问题,就是拖拽到垃圾桶但不放鼠标,这是垃圾桶颜色会变,如果这个时候我拖出垃圾桶,垃圾桶颜色不会reset
因为没有类似dragleave事件
强烈建议博主大大在文中加上 dragleave 事件的说明,我原本以为没有这个事件,有个效果死活做不出来。
+1
chrome 39,安装了 超级拖曳 1.9.0.3 拓展程序插件,导致demo演示有问题。2015-5-21 14:09:20
禁用后,程序演示正常。
请问对移动设备的drag事件有研究吗?我测试了一些代码,发现drag在移动设备上并不能好好工作。所以尝试了 touch,但发现touch又不支持 touchenter,touchleave事件,所以我不能捕获目标对象。即便在touchmove中,我也只能捕获拖拽对象,不能捕获目标对象。 如果通过touch点的坐标,遍历dom来获取目标对象,应该是个得不偿失的高发代码。 请指教至EMAIL
@陶留军 试试elementFromPoint~
你好,我遇到一个问题,想请教一下,我想用drag事件做一个产品图360全景功能,但是我不想有浏览器图片被拖放的事件发生,当我在ondragstart事件当中使用event.preventDefault()方法时,ondragover,也一并不产生效果了,请问有没有别的方法可以解决?
这个好像不好
setDragImage 这个函数在chrom和firefox、safari下不起做用,只有在opera下才有图片显示出来。。。
楼主:我现在在用drag&drop做一个上传图片的功能。页面初始话时我默认的设置了一个拖拽区域。还有个添加新拖拽区域的按钮。如果拖动图片到默认的拖拽区时是可以上传成功的。但是我添加新的拖拽区域后,拖拽总是选中最后一拖拽区来上传图片。(我用的是从桌面直接拉文件,不是在页面上拉)。貌似没办法监听到拖动的位置。
从桌面拖拽文件到浏览器,是html5的另外一个插件
HTML5新手,希望多交流哦。
用C#思想理解HTML5拖、放:http://www.deepleo.com/archives/1386
一点拙见,博主换链接吗?
这个属性android或者iphone支持吗??
不支持,在ios/android上请用Zepto插件
这个插件在win8平板上是可以的
您好,我想问一下,拖动的时候,会有两个层,一个是半透明的层,一个是实际的层,那个半透明的层是做什么的,怎么去掉呢
你好,请问当ondrop时,我想要div框就停在那个地方,应该怎么做呢,谢谢
非常支持。
今天照着写了一遍,发现drag事件在firefox上可以实现,但是在chrome上就实现不了了。
我所用的chrome浏览器是15.0.874.106 m的。
非常奇怪。
楼主你好,最近在实现一个网页IM,对话框的移动利用了drag属性,HTML结构为
收到的消息
实际过程中发现,设置a的draggable=true后,b中的文字无法进行选中操作了,只会触发a的drag事件,请求楼主帮忙检查下,谢谢了
这个例子只在Firefox中可以正常运行
写了个支持IE6+的Demo
http://leavingme.net/cnblogs/draganddrop/systemdemo.html
不知道您文章里所说的“但是会报不认识dataTransfer的错误”是咋回事,我好想没有遇到。
很好!支持……
博主,ie6貌似不可以
问张老师几个问题:
1.effectAllowed 属性具体是什么效果?我加不加那句没有看出效果上有什么差别啊?
2.setDragImage 函数是做什么用的呢?去掉似乎也无大碍。
3.每个函数底部的return true和return false有什么讲究吗?
4.在firefox下,ev.dataTransfer.clearData(“text”) 会抛出Modifications are not allowed for this document错误,不明原因。
可能一些问题问得有点笨,望勿见笑啊。
有了这个功能,页面可以做的更加智能化
好。。支持一下