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>

 

posted @ 2019-06-04 18:06  zhanglw  阅读(1143)  评论(0)    收藏  举报