HTML5 拖放 drag 及 文件拖拽上传
HTML5中提供了拖放的api,只需要监听拖放事件,就可以完成相应的功能。
1、可拖放元素
默认情况下,img 元素和 a 元素,以及文本都是可拖动的,而其他元素是不能。想要拖放某个元素,必须设置该元素的 draggable 属性为 true,当该属性为 false 时,将不允许拖放。
<img src="img/img1.png" alt="" draggable="false">
2、拖放事件
拖放事件是发生在两个地方的:一个是被拖放的元素上,另一个是拖放目标元素上的。
dragstart:被拖放元素上发生,按下鼠标键并开始移动是触发,此时光标变成”不能放”符号(圆环中有一条反斜线)
drag:被拖放元素上发生,鼠标拖动期间持续触发(类似mousemove)
dragend:被拖放元素上发生,拖动停止时触发
dragenter:拖放目标元素上发生,元素被拖到该目标上触发(类似mouseover)
dragover:拖放目标元素上发生,被拖放元素在放置目标范围内移动时持续触发
dragleave:拖放目标元素上发生,被拖放元素拖出了放置目标范围时触发
drop:拖放目标元素上发生,被拖放元素放置到了目标元素中时触发(在目标元素范围内释放鼠标键)
所有的元素都支持放置目标事件(dragenter,dragover,dragleave,drop),但只有一些元素默认允许放置,如input,大多数元素是不允许放置的,即不是有效的放置目标,不会发生drop事件。
为了让元素变成可放置,可以重写 dragenter 和 dragover 事件的默认行为,只要 阻止他的默认行为就可以了。
在Firefox中,drop事件的默认行为是打开被放到目标元素上的URL。即把图片或链接拖放到目标上,页面会转向该图片或者该链接页面;而拖放文本到目标上,则导致url错误。
为了改变这个情况,可以在 drop 事件的处理程序中 阻止 其默认行为
在Firefox中,拖放文本会跳到用 搜索引擎去搜索拖放的文本,阻止该行为,可以在 document.body 上添加一个 drop 事件处理程序,并在其中阻止事件传播。
3、dataTransfer 对象
dataTransfer对象是 拖放事件event中的一个属性,用于从被拖动元素项放置目标传递字符串格式的数据。
dataTransfer的属性和方法:
setData(format, data):设置拖拽事件中传递的数据,format 参数为数据类型。format,有多种,在HTML5中允许各种mime类型,但也兼容“text”和“url”,这两种会被映射成”text/plain“ 和 "text/uri-list"
在拖动文本框文本时,浏览器会自动调用 setData()方法,并以 "text"方式保存;拖放链接和图像时,会以"url" 方式保存。
可以手动地在 dragstart 事件处理程序中调用 setData() 保存自定义的传输数据
getData(format):获取数据,只能drop 事件中获取数据。
addElement(element):为拖动操作添加一个元素作为源元素,这个元素只影响数据。非标准方法Firefox支持,Chrome不支持
clearData(format):清除以特定格式保存的数据,若没有给定格式则清除所有数据,但除了文件files外,文件使用该方法清除;
setDragImage(element,x,y):为拖动操作指定一个图标,element 可以是 任何一种图像元素,可以是 <img>、 <canvas>等。x,y 是图标在光标下的坐标
files:返回被拖拽的 FileList(文件列表),相当于它是用户拖拽进浏览器的文件列表,是个 FileList 对象,有 length 属性,可以通过下标访问。
types:当前保存数据的类型,是一个字符串数组的集合,如果有文件则有一个是files,只读。
dropEffect:获取或设置 被拖动的元素在放置目标上能够执行那些放置行为。每个只是改变拖动元素到放置目标上的光标类型,但具体数据如何操作可有用户自定义。在 dragenter 事件处理程序中设置
"none":不能把元素放在这里,默认值(文本框除外)
"move":被拖拽元素将被移动到目标元素内
"link":被拖拽元素将以超链接的形式打开资源
"copy":被拖拽元素将被复制到目标元素内
effectAllowed:获取或设置允许拖动元素进行哪一种 dropEffect 行为。在dragstart 事件处理程序中设置。
"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
4、示例
<div id="div1">hello drag</div>
<div id="div2">
<input type="text" id="input1">
<input type="text" id="input2">
<img id="img1" src="img/date.png" alt="" draggable="false">
<a href="https://www.baidu.com">baidu</a>
<input type="file" id="files">
</div>
<div id="div3" style="width: 200px;height: 200px;border: 1px solid black;"></div>
<div id="div4" style="width: 100px;height: 100px;border: 1px solid black;" draggable="true">可拖动</div>
<div id="div5" style="width: 100px;height: 100px;border: 1px solid black;" draggable="false">不可拖动</div>
window.onload=function(){
let div1 = document.querySelector("#div1");
let div3 = document.querySelector("#div3");
let div4 = document.querySelector("#div4");
let div5 = document.querySelector("#div5");
let input1 = document.querySelector("#input1");
let input2 = document.querySelector("#input2");
let img1 = document.querySelector("#img1");
//拖拽div1中的文本
div1.addEventListener("dragstart",function(e){
// console.log("dragstart");
console.log(e.type);
e.dataTransfer.setData("text","hello set data");
e.dataTransfer.setData("url","https://www.baidu.com");
// e.dataTransfer.dropEffect = "move";
},false);
div1.addEventListener("drag",function(e){
// console.log("drag");
console.log(e.type);
},false);
div1.addEventListener("dragend",function(e){
// console.log("dragend");
console.log(e.type);
},false);
input2.addEventListener("dragstart",function(e){
// console.log("dragstart");
console.log(e.type);
},false);
// 将文本拖放到 input 框中
input1.addEventListener("dragenter",(e)=>{
// console.log("dragenter");
console.log(e.type);
},false);
input1.addEventListener("dragover",(e)=>{
// console.log("dragover");
console.log(e.type);
},false);
input1.addEventListener("dragleave",(e)=>{
// console.log("dragleave");
console.log(e.type);
},false);
input1.addEventListener("drop",(e)=>{
// console.log("drop");
console.log(e.type);
console.log(e.dataTransfer.getData("text"));
console.log(e.dataTransfer.types);
// e.preventDefault();
},false);
//将div 设置为允许放置drop
div3.addEventListener("dragover",(e)=>{
e.preventDefault();
console.log("dragOver: dropEffect = " + e.dataTransfer.dropEffect + " ; effectAllowed = " + e.dataTransfer.effectAllowed)
//e.dataTransfer.dropEffect = "move"
},false);
div3.addEventListener("dragenter",e=>{
e.preventDefault();
e.dataTransfer.dropEffect = "copy";
},false);
div3.addEventListener("drop",e=>{
console.log(e);
console.log(e.dataTransfer.getData("url"));
console.log(e.dataTransfer.getData("text"));
console.log(e.dataTransfer.types);
e.preventDefault(); //兼容firefox,阻止Firefox打开url
if(e.dataTransfer.getData("text")){
e.target.appendChild(document.getElementById(e.dataTransfer.getData("text")));
}
},false);
div4.addEventListener("dragstart",e=>{
e.dataTransfer.setData("text",e.target.id);
e.dataTransfer.setDragImage(img1,10,10); // 设置拖动背景图标
console.log("dragOver: dropEffect = " + e.dataTransfer.dropEffect + " ; effectAllowed = " + e.dataTransfer.effectAllowed);
e.dataTransfer.effectAllowed = "copy"; // 在 dragstart 事件中,设置dataTransfer.effectAllowed
},false);
//阻止 firefox搜索 拖放的文本
document.body.ondrop = function (event) {
// event.preventDefault();
event.stopPropagation();
};
}
文件拖拽上传
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style media="screen">
* {margin:0; padding:0; list-style: none}
.box {width:400px; height:200px; background:#CCC; border:1px solid black; line-height:200px; position:absolute; left:50%; top:50%; margin-left:-200px; margin-top:-100px; text-align:center; display:none;}
.img_list {overflow:hidden;}
.img_list li {float:left; width:200px; height:200px; border:3px solid #666; margin:10px; position:relative;}
.img_list li img {width:100%; height:100%;}
.img_list li .del_btn {position:absolute; right:0; top:0;}
</style>
<script>
window.onload=function (){
let oUl=document.querySelector('.img_list');
let oBox=document.querySelector('.box');
let timer;
document.addEventListener('dragover', (ev)=>{
clearTimeout(timer);
oBox.style.display='block';
timer=setTimeout(function (){
oBox.style.display='none';
}, 300);
ev.preventDefault();
}, false);
oBox.addEventListener('dragenter', ()=>{
oBox.innerHTML='请松手';
}, false);
oBox.addEventListener('dragleave', ()=>{
oBox.innerHTML='请把文件拖到这儿';
}, false);
oBox.addEventListener('drop', (ev)=>{
Array.from(ev.dataTransfer.files).forEach(file=>{
if(!file.type.startsWith('image/')){
return;
}
let reader=new FileReader();
reader.onload=function (){
let oLi=document.createElement('li');
oLi.file=file;
oLi.innerHTML='<img src="a.png" alt=""><a href="javascript:;" class="del_btn">删除</a>';
let oImg=oLi.children[0];
oImg.src=this.result;
let oBtnDel=oLi.children[1];
oBtnDel.onclick=function (){
oUl.removeChild(oLi);
};
oUl.appendChild(oLi);
};
reader.readAsDataURL(file);
});
ev.preventDefault();
}, false);
//真的上传
let oBtnUpload=document.querySelector('#btn_upload');
oBtnUpload.onclick=function (){
let data=new FormData();
Array.from(oUl.children).forEach(li=>{
data.append('f1', li.file);
});
//
let oAjax=new XMLHttpRequest();
//POST
oAjax.open('POST', `http://localhost:8080/api`, true);
oAjax.send(data);
oAjax.onreadystatechange=function (){
if(oAjax.readyState==4){
if(oAjax.status>=200 && oAjax.status<300 || oAjax.status==304){
alert('成功');
}else{
alert('失败');
}
}
};
};
};
</script>
</head>
<body>
<ul class="img_list">
<!--<li>
<img src="a.png" alt="">
<a href="javascript:;" class="del_btn">删除</a>
</li>
<li>
<img src="b.png" alt="">
<a href="javascript:;" class="del_btn">删除</a>
</li>-->
</ul>
<input type="button" name="" value="上传" id="btn_upload">
<div class="box">
请把文件拖到这儿
</div>
</body>
</html>

浙公网安备 33010602011771号