在HTML5之前,如果要实现一个元素的拖放效果,需要结合 onmousedown 、 onmousemove 、 onmouseup 事件,还有鼠标位置获取的知识点,来完成元素的拖动的效果。所以很麻烦。在HTML5中,只要将某个元素的 draggable 属性设置为 true,该元素就可以实现拖放的效果。并且拖放过程中也能触发很多事件
HTML5为所有HTML元素规定了一个draggable属性,控制元素是否可以拖动。图像、链接和被选中的文本的draggable属性默认为true,其他元素默认为false。
draggable属性的值如下:
属性值 | 说明 |
---|---|
true | 内容可被拖动。 |
false | 内容不可被拖动。 |
auto | 内容执行默认的浏览器行为(图像、链接和被选中的文本可被拖动,其他元素不能) |
支持 draggable 属性的浏览器有: IE9+、FF4+、Safari 5+、Chrome、Opera 12+。Opera 11.5- 不支持拖放功能。
draggable属性的兼容性处理:
(1) Firefox:需要添加ondragstart事件处理程序,并在dataTransfer中保存一些信息;
(2) IE9-通过mousedown事件调用dragDrop()能够让任何元素可拖动;
(3) Safari 4- 必须给相应元素设置 CSS 样式:
*[draggable = true] {
-khtml-user-drag: element;
}
dropzone可以创建一个放置区域。
属性值 | 作用 |
---|---|
copy | 表示将允许的元素放到该元素上时,会将拖拽数据复制到目标元素上。 |
move | 表示将允许的元素放到该元素上时,会将数据移动到目标元素上。 |
link | 表示将允许的元素放到该元素上时,将链接数据到目标元素上。 |
拖放事件触发次序:
dragstart -> drag(持续触发) -> dragenter -> dragover(持续触发) -> dragleave或drop -> dragend。
拖动某元素时,将依次触发以下事件:
dragstart:按下鼠鼠标键并开始移动时,被拖动元素上触发 dragstart 事件;
drag:触发 dragstart 事件后,随即触发 drag 事件,而且元素拖动期间会持续触发该事件;
dragend:拖动停止时(释放鼠标、无论放置目标是否有效)触发 dragend 事件;
当某个元素被拖动到一个有效的放置目标元素时,依次触发下列事件:
dragenter:元素进入到目标元素上时触发事件;
dragover:紧随 dragover 事件,被拖动元素在目标元素范围内移动时会持续触发该事件;
dragleave或drop:元素拖出了放置目标,则 dragover 事件不再发生,触发 dragleave 事件;如果被拖元素放到了目标元素上,则触发 drop 事件;
所有元素都支持放置目标事件,但多数元素默认是不允许放置的。重写 dragenter 和 dragover 事件的默认行为,可以把任何元素变成有效的放置目标。
dropArea.addEventListener("dragenter", preventDefault(event), false);
dropArea.addEventListener("dragover", preventDefault(event), false);
// 阻止 Firefox 打开 URL
dropArea.addEventListener("drop", preventDefault(event), false);
// 阻止默认事件和事件冒泡
function preventDefault(event) {
event = event || window.event;
event.stopPropagation();
event.preventDefault();
}
Firefox 3.5+ 中,放置事件的默认行为是打开放到目标上的URL。如果是图像则打开图像,如果是文本则会导致无效 URL 错误(不安装拖拽插件的情况下)。所以还要取消 Firefox 中 drop 事件的默认行为,阻止它打开 URL。
注意1: drag和dragover是持续触发的。拖放文件到浏览器中时,需要在dragover和drop事件处理器中阻止默认行为(preventDefault())。因为从其他应用软件或是文件中拖东西进入浏览器中,默认的行为是浏览器将当前页面重定向到被拖拽元素所指向的资源上。
注意2: 在被拖元素上触发dragstart事件后,则该元素的mousemove,mouseover,mouseenter,mouseleave,mouseout事件均不会被触发了。
dataTransfer对象是拖放事件对象的一个属性,用于从被拖动元素向放置目标传递字符串格式的数据。
方法 | 说明 |
---|---|
clearData(format) | 清除以特定格式保存的数据 。 |
getData(format) | 从 dataTransfer 对象中读取指定类型的值,参数是 MIME 类型。 |
setData(format, data) | 为 dataTransfer 对象指定特定格式的数据,这些数据只能在 ondrop 处理程序中读取。 |
setDragImage(element, x, y) | 指定一个元素拖动发生时显示在光标下方,三个参数分别是要显示的 HTML元素和光标在显示元素中的x、y坐标。 |
addElement(element) | 为拖动操作添加一个元素(即增加作为拖动源而响应的回调对象)。如果想要让某个元素跟随被拖拽元素一同被拖拽,可使用该方法。 |
IE只定义了“text”和“URL”两种有效的数据类型,而HTML5则对此加以扩展,允许指定各种MIME类型。考虑到向后兼容,HTML5也支持“text”和“URL”,但这两种类型会被映射为“text/plain”和“text/uri-list”。如下所示:
text/html:文本文字格式;
text/plain:HTML代码格式;
text/xml:XML字符格式;
text/url-list:URL格式列表;
Firefox在其第5个版本之前不能正确地将“URL”和“text”映射为“text/uri-list”和“text/plain”。但是却能把“Text”映射为“text/plain”。为了更好地在跨浏览器的情况下从dataTransfer对象取得数据,最好在取得URL数据时检测两个值,而在取得文本数据时使用“text”。
var dataTransfer = event.dataTransfer;
//读取URL
var url = dataTransfer.getData("url") || dataTransfer.getData("text/uri-list");
//读取文本
var text = dataTransfer.getData("Text");
属性 | 说明 |
---|---|
Property | Description |
dropEffect | 获取或设置被拖动元素能够执行哪中放置行为,不同的行为显示相应的光标。 |
effectAllowed | 表示允许拖动元素的哪种 dropEffect。 |
files | 返回被拖放文件的FileList对象。 |
types | 返回ondragstart事件中传递的数据类型的类似数组的集合。 |
dropEffect的属性值分别有:
(1) none:不能放置拖动元素(除文本框以外所有元素的默认值);
(2) move:应该把元素移动到放置目标;
(3) copy:应该把拖动元素复制到放置目标;
(4) link:应该在放置目标上打开拖动元素(拖动元素必须是有 URL 的链接)。
effectAllowed的属性值分别有:
(1) uninitialized:被拖动元素没有设置放置行为;
(2) none:被拖动元素不允许有任何行为;
(3) copy:只允许 copy 值的 dropEffect;
(4) move:只允许 move 值的 dropEffect;
(5) copeLink:copy 和 link 值的 dropEffect;
(6) copeMove:copy 和 move 值的 dropEffect;
(7) linkMove:link 和 move 值的 dropEffect;
(8) all:允许任意 dropEffect。
注意:使用dropEffect属性时必须在ondragenter中针对放置目标设置,只有搭配effectAllowed属性时才有用。必须在ondragstart中设置 effectAllowed。
html:
<head><meta charset="UTF-8">
<title>drag and droptitle>
<style type="text/css">
#source {
width:100px;
height:100px;
background:cornflowerblue;
margin:30% auto;
}
.droparea {
width:300px;
height:300px;
border:2px solid #777;
margin:20px 20px;
float:left
}
style>
head>
<body>
<div class="droparea" draggable="false">
<div id="source" draggable="true">该元素可拖拽div>
div>
<div class="droparea" draggable="false">div>
<div class="droparea" draggable="false">div>
<div class="droparea" draggable="false">div>
body>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js">script>
<script type="text/javascript" src="./js/drag_2.js">script>
html>
javascript:
/** 拖放事件由不同的元素产生。一个元素被拖放,他可能会经过很多个元素上,最终到达想要放置的元素内。这里,我暂时把被拖放的元素称为源对象,被经过的元素称为过程对象,到达的元素我称为目标对象。不同的对象产生不同的拖放事件。
源对象:
dragstart:源对象开始拖放。
drag:源对象拖放过程中。
dragend:源对象拖放结束。
过程对象:
dragenter:源对象开始进入过程对象范围内。
dragover:源对象在过程对象范围内移动。
dragleave:源对象离开过程对象的范围。
目标对象:
drop:源对象被拖放到目标对象内。*/
(function(window, undefined){
//一、定义全局数据
//二、首页JS功能
var Index = (function(){
var dragEl;
//init初始化
var init = function(){
bindEvent();
};
var bindEvent = function(){
var sourceEl = document.getElementById('source');
var targetEls = document.getElementsByClassName('droparea');
for(var i = 0; i < targetEls.length; i++){
targetEls[i].ondragenter = function(event){
//event.currentTarget.style.background = 'rgba(133, 254, 255, 0.3)';
}
targetEls[i].ondragover = function(event){
event.preventDefault();
}
targetEls[i].ondragleave = function(event){
//event.currentTarget.style.background = 'rgba(243, 243, 243, 0)';
}
targetEls[i].ondrop = function(event){
event.preventDefault();
try{
dragEl.textContent = '该元素可拖拽';
dragEl.parentNode.removeChild(dragEl);
event.target.appendChild(dragEl);
}catch(err){
//console.info('error');
}finally{
dragEl = null;
}
}
}
sourceEl.ondragstart = function(event){
event.dataTransfer.setData("text/plain", event.target.id);
var img = new Image();//定义拖动图像
img.src = 'images/001.png';
event.dataTransfer.setDragImage(img, 5, 5);
event.dataTransfer.dropEffect = "copy";//设置改变当前选中的操作,可选值为none,copy,link和move。
dragEl = event.target;
dragEl.textContent = '正在被拖拽'
}
sourceEl.ondrag = function(event){}
sourceEl.ondragend = function(event){}
};
return {
init : init
};
})();
$(function(){
Index.init();
});
})(window);