您现在的位置是:首页 > 前端学习 > Web前端Web前端

拖放功能(第八章)(图文)

第十三双眼睛2020-02-13【Web前端】人已围观

简介在web应用中,良好的用户体验是设计师们一直的追求,拖拽体验就是其中之一,在HTML5之前,已经可以使用事件mousedown,mousemove,mouseup,巧妙的实现了页面内的拖放操作,但是拖放的操作只局限在浏览器内部,HTML提供拖放的API,不但能直接实现拖放操作,而且拖放的范围已经超出浏览器的边界,HTML5提供的文件API,支持拖拽多个文件并上传,这一革命性的支持,为移动互联网应用进一步铺平道路。
本章知识点如下:
1HTML中的拖放API
2HTML中的文件API
3鼠标拖放事件

拖放API
HTML5的拖放API,基本包括3个方面,首先是为页面元素提供了拖放特性,其次是为了鼠标事件增加了拖放事件,最重要的是提供了用于存储拖放数据的DataTransfer对象,下面我们分3个方法去讲解。

新增的draggable特性
draggable特性,是用于定义页面元素是否允许用户拖放,该特性有三个值,true,false,auto,通常,大部分的页面元素是不可拖放的,如果要把元素变成可以拖放的,则可以设置draggable特性如下:<div draggable="true"></div>,另外img元素和a元素(需要指定href)默认是可以拖放的。

新增的鼠标拖放事件
为了拖放控制更加具体,HTML5提供了7个与拖放相关的鼠标影响事件,而这7个事件会响应在不同的元素上。下面我们按照响应的事件先后顺序逐个介绍。
1dragstart事件
开始拖拽时触发的事件,事件的作用对象是被拖拽的元素。
2drag事件
拖放过程中触发的事件,事件的作用对象是被拖拽的元素。
3dragenter事件
有拖放的元素进入本元素的范围内时触发,事件的作用对象时拖放过程中鼠标经过的元素。
4dragover事件
有拖放的元素正在本元素的范围内移动时触发,事件的作用对象时拖放过程中鼠标经过的元素。
5dragleave事件
有拖放的元素礼开本元素中时触发,事件的作用对象是拖放过程中鼠标经过的元素。
6drop事件
有拖放的元素被拖放到本元素时触发,事件的作用对象是拖放的目标元素
7dragend事件
拖放操作结束时触发,事件的作用对象是被拖拽的元素。
在拖放过程中,我们可以利用这7个事件来实现我们需要的功能。

DataTransfer对象
HTML5提供了DataTransfer对象,用以支持拖拽数据的存储。使用拖放的目的,就是希望在拖放过程中有数据交换,而DataTransfer对象就充当了这种媒介,DataTransfer对象有自己的属性和方法,可以完成拖拽数据的各种处理。
1dropEffect属性
设置或者获取拖拽操作的类型和要显示的光标类型。如果该操作效果与起初设置的effectAllowed效果不符,则拖拽操作失败。可以设置修改,包含这几个值,none,copy,link,和move.
2effectAllowed属性
设置或者获取数据传送操作可应用于该对象的数据源,可以指定值为none ,copy, copyLink,copyMove,link,llinkMove,move,all,uninitialized.
3type属性
获取在dragstart事件触发时为元素存储数据的格式,如果时外部文件拖拽,则返回Files
4files
获取存储在DataTransfer对象中的正在拖放的文件列表FileList,可以使用数组的方式遍历。
5clearData方法
清除DataTransfer中的数据,语法如下:clearData([sDataFormat]),[sDataFormat]为可选参数,参数可以取值:text,url,file,html,image,即可以删除指定格式的数据,如果该参数省略,则删除所有数据。
6setData()方法
向内存中的DataTransfer对象添加指定格式的数据。语法如下:
setData([sDataFormat],[data]);
参数说明,[sDataFormat]数据参数类型,可取值为text,url,[data]为数据,类型为字符串或者url地址。
7getData()方法
从内存中的DataTransfer对象中获取数据,语法如下:
getData([sDataFormat])
参数说明,[sDataFormat]为数据参数类型,可取值为text.url.
8setDragImage()方法
设置拖放时,跟鼠标移动的图片。语法如下;
setDragImage([imgElement],[x],[y])
参数说明,[imgElement]表示图片对象,x,y分别表示相对于鼠标位置的横坐标和纵坐标。
9addElement()方法
添加一起跟随拖拽的元素,如果想让某个元素跟着被拖拽元素一起移动,则使用此方法。使用方法如下:
addElement([element]);

实战:拖放元素的内容
下面我们使用前面学习的拖放API,来实现拖放页面中元素的内容。即把一个页面元素里的内容通过拖放的方式,在另一个元素内产生一个副本。分4个步骤来处理。
1设计页面元素,在页面中添加两个元素,分别作为拖放的源元素和目标元素,并设置样式表,其中源元素内部包含文字和图片内容。目标元素的内容为空,源元素设置draggable属性为true.表示可以被拖放。
2添加ondragstart事件。给拖放的源元素添加ondragstart监听事件,事件触发时把源元素里的内容追加到DataTransfer对象中,最后把添加监听事件的处理函数添加到window.onload中
3添加dragover监听事件,给拖放的目标元素添加dragover监听事件,事件触发时改变目标元素的样式,并屏蔽了浏览器的默认处理事件,最后把添加监听事件的处理函数添加到window.onload中。
4添加ondrop监听事件,给拖放的目标元素添加ondrop监听事件,事件触发时,获取DataTransfer对象中的数据,并追加至目标元素中,同时还原了样式,最后把添加监听事件的处理函数添加至window.onload中,至此,拖放页面元素的内容,已经完成了。
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>拖放页面的内容</title>
    </head>
    <body>
        <div id="dragSource" draggable="true">
            拖着里<button type="button">点击一下</button>
        </div>
        <div id="dragTarget" style="width: 500px;height: 300px;background-color: #1B6D85;"></div>
    </body>
    <script type="text/ecmascript">
        function dragStart(){
            var source = document.getElementById('dragSource');
            source.addEventListener('dragstart',function(e){
                e.dataTransfer.setData('text/plain',e.target.innerHTML);
                e.dataTransfer.effectAllowed="copy"
            },false)
        }
        window.addEventListener('load',dragStart(),false);
        
        function dragOver(){
            var target = document.getElementById('dragTarget');
            target.addEventListener('dragover',function(e){
                this.className="dragOver";
                e.preventDefault();
            },false)
        }
        window.addEventListener('load',dragOver(),false);
        
        function drop(){
            var target = document.getElementById('dragTarget');
            target.addEventListener('drop',function(e){
                var data = e.dataTransfer.getData('text/plain');
                this.innerHTML +=data;
                e.dataTransfer.dropEffect="copy";
                this.className="";
            },false)
        }
        window.addEventListener('load',drop,false);
    </script>
</html>


效果如图所示:

文件API
HTML5提供了一个关于文件操作的API,我们可以通过编程的方式选择或者访问文件,使得从web上访问本地文件系统变得十分简单。文件API主要涉及fileList对象,file对象,blob接口,filereader接口。
1multiple特性
HTML5仍然沿用传统的文件上传的方式,借助file类型的表单元素来实现文件的上传,与之前不同的是,HTML5为file类型的表单元素新增了multipul属性和accept属性。
multiple特性允许同时选择多个文件进行上传,在HTML5之前,只允许选择一个文件进行上传,而在HTML5中,可借助multiple特性同时选择多个文件进行上传,使用方法如下:<input type="file" multiple="true" />,同时选择多个文件上传,得到的是一个fileList对象,该对象是一个file对象的列表,关于这两个对象会在下一节讲述。
2accept
accept特性,规定了可通过文件上传提交的文件类型,HTML5规范企图使用accept特性限制文件上传只能接收指定类型的文件,但是目前主流的浏览器并没有做这样的限制,仅实现了在打开文件窗口时,默认选择指定的文件类型。accept特性使用方法如下:<input type="file" multiple="true" accept="image/gif"/>
这行代码说明只接受gif格式的文件,但在实际使用中,在选择上传文件时,默认仅显示gif格式的文件,当然也可以选择其他类型的文件上传,没有实际的限制。

FileList对象与file对象
当用户在file类型的表单元素中,同时选择多个文件时,可以通过编程的方式获得一个文件列表,即FileList对象,里面的每个文件是一个File对象。
FileList对象是File对象的一个集合,可以使用数组的方式遍历FileList对象里的每个File对象。
例子:遍历FileList对象。
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>遍历FileList对象</title>
    </head>
    <body>
        <form action="" method="post">
            <input type="file" id="files" multiple="multiple"/>
            <input type="button" value="显示文件" onclick="showFiles()"/>
            <p id="msg"></p>
        </form>
    </body>
    <script type="text/javascript">
        function showFiles(){
            var filesList = document.getElementById("files").files;
            var file=null;
            var msg = document.getElementById("msg");
            for(var i=0;i<filesList.length;i++){
                file = filesList[i];
                msg.innerHTML +=file.name+";<br/>"
            }
        }
        
    </script>
</html>


Blob对象
Blob接口代表原始二进制数据,通过Blob对象的slice方法,可以访问里面的字节数据,Blob接口还有两个属性:size和type.
1size属性
表示Blob对象的字节长度,Blob对象的二进制数据,可借助FileReader接口读取,如果Blob对象没有数据,则size为0。
2type属性
表示Blob对象的MIME类型,如果是位置类型,则返回一个空字符串,使用type属性获取文件的MIME类型,可以更加精确的确定文件的类型,可避免因更改文件的扩展名而造成的文件类型误判。
3slice方法
使用slice方法可以实现文件的切割,并返回一个新的Blob对象。
4File对象与Blob对象
File对象继承了Blob对象,所以Blob对象的属性和方法,File对象也可以使用。
5实例介绍
File对象可以像Blob对象一样去使用size属性和type属性。下面的实例,我们就使用这两个属性获取文件上传的基本数据信息。
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>获取文件的大小和类型</title>
    </head>
    <body>
        <form id="" action="" method="post">
            <input type="file" id="files" multiple="multiple" accept="image/*"/>
            <input type="button" value="显示文件数据" onclick="showType()" />
            <p id="msg"></p>
        </form>
    </body>
    <script type="text/javascript">
        function showType(){
            var files = document.getElementById("files").files;
            var msg = document.getElementById("msg");
            var file =null;
            for(var i=0;i<files.length;i++){
                file = files[i];
                msg.innerHTML+="字节长度:"+file.size+"<br/>";
                msg.innerHTML+="文件类型:"+file.type+"<br/>";
            }
        }
    </script>
</html>


具体效果如下图所示:

FileReader接口
FileReader接口提供了一些读取文件的方法,与一个包含读取结果的事件模型。作为File API的一部分FileReader接口主要是把文件读入内存,并读取文件中的数据。
由于部分早期版本的浏览器,没有实现FileReader接口,所以在使用FileReader接口之间,有比要检测一下浏览器的支持情况。检测方法如下:
<script type="text/javascript">
        if(typeof FileReader =="undefined"){
            alert("未实现FileReader接口");
        }else{
            var reader = new FileReader();
        }
    </script>
1接口的属性
FileReader接口拥有3个属性,分别用于返回读取文件的状态,数据和读取文件时发生的错误。
readState属性(只读)
读取文件的状态,该状态有3个值:
EMPTY,值为0,表示新的FileReader对象已经构建,且没有调用任何读取方法时的默认状态。
LOADING,值为1,表示有读取文件的方法正在读取File对象或者Blob对象,且没有错误发生。
DONE,值为2,表示读取文件结束,可能整个File对象或者Blob对象已经全部读入内存中,或者在文件读取的过程中出现错误,或者读取过程中使用了abort方法进行强行中断。
result属性,只读,获取已经读取的文件数据,如果时图片,将返回base64格式的图片数据。
error属性,获取读取文件过程中发生的错误,该错误包含4种类型。
notfounderror:找不到读取的资源文件,FileReader接口会返回NotFoundError错误,同时,读取文件的方法也会抛出NotFoundError错误异常。
SecurityError:发生安全错误,FileReader接口会返回SecurityError错误,同时读取文件的方法也会抛出SecurityError错误异常。
NotReadableError:无法读取的错误,FileReader接口会返回NotReadableError错误,同时,读取文件的方法也会抛出NotReadableError错误异常
EncodingError:编码限制的错误,通常是数据的URL表示的网址长度收到限制。

2接口的方法
FileReader接口拥有5个方法:其中4个用于读取文件。另一个用来中断读取过程。
1readAsArrayBuffer,将文件读取为数组缓冲区,该方法的语法如下:reader.readAsArrayBuffer(<blob>);
参数说明:<blob>表示一个blob对象的文件,readAsArrayBuffer方法就是把该blob对象的文件读取问数组缓冲区。
2reader.readAsBinaryString();将文件读取问二进制字符串,该方法的语法如下:reader.readAsBinaryString(<blob>);
参数说明:<blob>表示一个blob对象的文件,该方法就是把该blob对象的文件读取为二级制字符串。
3reader.readAsText();将文件读取为文本。该方法的语法如下:reader.readAsText(<blob>,<encoding>);
参数说明:<blob>表示一个blob对象的文本,readAsText()方法就是把该blob对象的文件读取为文本,<encoding>表示文本的编码方式,默认值为utf-8
4reader.readAsDataURL();将文件读取为DataUrl字符串,该方法的语法如下:reader.readAsDataURL(<blob>);
参数说明:<blob>表示一个blob对象的文件,readAsDataURL()方法就是把该blob对象的文件读取为DataUrl字符串。
5reader.ABORT();用于中断读取操作,该方法的语法如下:reader.ABORT();该方法没有参数。

3接口事件
loadstart事件:开始读取数据时触发的事件
progress事件:正在读取数据时触发的事件
load事件:成功完成数据读取时触发的事件
abort事件:中断读取数据时触发的事件
error事件:读取数据发生错误时触发的事件
loadend事件:结束读取数据时触发的事件,数据读取可能成功也可能失败。
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>接口的方法实例</title>
    </head>
    <body>
        <form action="" method="post">
            <input type="file" id="files" multiple="multiple" accept="image/*"/>
            <input type="button" value="读取为数组缓冲区" onclick="ReadAs('ArrayBuffer')" />
            <input type="button" value="读取为二进制" onclick="ReadAs('BinaryString')" />
            <input type="button" value="读取为文本" onclick="ReadAs('text')"/>
            <input type="button" value="读取为图片" onclick="ReadAs('dataurl')"/>
            <p id="result"></p>
        </form>
    </body>
    <script type="text/javascript">
        function ReadAs(action){
            var blob = document.getElementById("files").files[0];
            if(blob){
                var reader = new FileReader();
                switch(action.toLowerCase()){
                    case "binarystring":
                    reader.readAsBinaryString(blob);
                    break;
                    case "arraybuffer":
                    reader.readAsArrayBuffer(blob);
                    break;
                    case "text":
                    reader.readAsText(blob);
                    break;
                    case "dataurl":
                    reader.readAsDataURL(blob);
                    break;
                }
                reader.onload =function(e){
                    var result = this.result;
                    if(/Image\/\w+/.test(blob.type)&&action.toLowerCase()=="dataurl"){
                        document.getElementById("result").innerHTML="<img  src='"+result+"'/>"
                    }else{
                        document.getElementById("result").innerHTML=result;
                    }
                }
            }
        }
    </script>
</html>


结果如下图所示:

5接口的事件实例
FileReader接口提供了6个事件,下面我们通过一个实例,来查看各个事件的响应顺序。
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>接口的事件响应顺序</title>
    </head>
    <body>
        <form action="" method="post">
            <input type="file" id="files" multiple="multiple" accept="image/*"/>
            <input type="button" value="读取文件"  onclick="loadevent()"/>
            <p id="msg"></p>
        </form>
    </body>
    <script type="text/javascript">
        function loadevent(){
            var blob = document.getElementById("files").files[0];
            var message = document.getElementById("msg");
            var reader = new FileReader();
             reader.onloadstart = function(e){
                 message.innerHTML+="loadstart;"
             }
             reader.onprogress = function(e){
                 message.innerHTML +="onprogress;"
             }
             reader.onload = function(e){
                 message.innerHTML +="load;";
             }
             reader.onabort = function(e){
                 message.innerHTML +="abort;";
             }
             reader.onerror = function(e){
                 message.innerHTML +="error;";
             }
             reader.onloadend = function(e){
                 message.innerHTML +="loadend;"
             }
             reader.readAsDataURL(blob);
        }
        
    </script>
</html>


具体结果如下图所示:

实战:把图片拖入浏览器
在HTML5之前,很难实现超出浏览器边界的事情,如,把电脑上的文件拖入浏览器,就很难实现,本节我们就用前面学习的API和文件API来实现这样的事情。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>把图片拖入浏览器</title>
        <style>
            #dropTarget{
                width: 300px;
                height: 300px;
                margin: 10px 0 0 0;
                border: 1px solid #015eac;
            }
            #dropTarget img{
                width: 100px;
                height: 60px;
                margin: 5px;
            }
        </style>
    </head>
    <body>
        <div>把图片拖入下面的方框</div>
            
        <div id="dropTarget"></div>
    </body>
    <script type="text/javascript">
        var target = null;
        function dropHandle(e){
            alert("aaa");
            var fileList = e.DataTransfer.files,
            fileType;
            for(var i=0;i<fileList.length;i++){
                fileType = fileList[i].type;
                if(fileType.indexOf('image')!=-1){
                    alert('请拖拽图片');
                    return ;
                }
                loadImg(fileList[i]);
            }
        }
        function loadImg(file){
            alert("bbb");
            var reader = new FileReader();
            reader.onload = function(e){
                var oImg = document.createElement('img');
                oImg.src = this.result;
                target.appendChild(oImg);
            }
            reader.readAsDataURL(file);
            alert("ccc");
        }
        
        window.onload = function(){
            target = document.getElementById('dropTarget');
            target.addEventListener('dragover',function(e){
                e.preventDefault();
            },false);
            target.addEventListener('drop',dropHandle,false)
        }
    </script>
</html>


结果如下图所示:







 

Tags:HTML   前端   拖放

很赞哦! ()

随机图文

文章评论

    共有条评论来说两句吧...

    用户名:

    验证码:

本站推荐

站点信息

  • 网站名称:JavaStudy
  • 建站时间:2019-1-14
  • 网站程序:帝国CMS7.5
  • 文章统计242篇文章
  • 标签管理标签云
  • 统计数据百度统计
  • 微信公众号:扫描二维码,关注我们