首页>前端教程>JavaScript教程

HTML5新增的拖拽上传API

早期拖拽的实现很麻烦,需要利用mousedown,mousemove,mouseup结合事件对象来实现,相当麻烦。

<div class="box"></div>
<script>
    const oDiv = document.querySelector('.box');
    oDiv.onmousedown = function(e){
        let offsetx = e.offsetX;
        let offsety = e.offsetY;
        this.style.backgroundColor = '#f30';
        //把事件放在document上,防止抖动
        document.onmousemove = function(e){
            oDiv.style.left = e.x - offsetx + 'px';
            oDiv.style.top = e.y - offsety + 'px';
        }
        document.onmouseup = function(){
            document.onmousemove = null;
        }
    }
</script>

HTML5提供了拖拽API后,实现拖拽和拖放就有规范可循,也更简单了。

一、拖拽

1.1、拖拽对象

把元素设置为可拖拽。

设置元素的属性draggable 为true。

<div draggable = "true">
    拖拽我
</div>
<img src="images/summer.jpg" alt="" draggable>

1.2、事件

1、ondragstart

事件:当拖拽元素开始被拖拽的时候触发的事件,此事件作用在被拖曳元素上

2、ondrag

一直在被拖动,此事件作用在被拖曳元素上

3、ondragenter

当拖曳元素进入目标元素的时候触发的事件,此事件作用在目标元素上

4、ondragover

拖拽元素在目标元素上移动的时候触发的事件,此事件作用在目标元素上

5、ondrop

被拖拽的元素在目标元素上同时鼠标放开触发的事件,此事件作用在目标元素上

6、ondragleave

离开目标元素,此事件作用在目标元素上

7、ondragend 事件:当拖拽完成后触发的事件,此事件作用在被拖曳元素上

    <img src="images/summer.jpg" alt="" draggable>
    <div class="box"></div>

    <script>
        var oImg = document.querySelector('img');
        var oDiv = document.querySelector('.box');

        // 图片是被拖拽的元素
        oImg.ondragstart = function(){
            console.log('我被拖动了');
        }
        oImg.ondrag = function(){
            console.log('我一直在被拖动了');
        }
        oImg.ondragend = function(){
            console.log('我被放下了');
        }
        // div是目标元素
        oDiv.ondragenter =  function(){
            console.log('进入我了');
        }
        oDiv.ondragover =  function(e){
            //要阻止默认行为,否则ondrop无效
            e.preventDefault();
            console.log('在我上空盘旋');
        }
        oDiv.ondragleave =  function(){
            console.log('离开我了');
        }
        oDiv.ondrop =  function(){
            console.log('放在我里面了');
            this.appendChild(oImg)
        }
    </script>

在ondragover中一定要执行preventDefault(),否则ondrop事件不会被触发。另外,如果是从其他应用软件或是文件中拖东西进来,尤其是图片的时候,默认的动作是显示这个图片或是相关信息,并不是真的执行drop。此时需要用document的ondragover事件把它直接干掉。

1.3、拖拽三部曲

拖拽至少有三个事件

        const oUl = document.querySelector('.course');
        const oLis = document.querySelectorAll('.item');
        const oNewUl = document.querySelector('.f-course');
        const oNewLis = oNewUl.getElementsByTagName('li');
        console.log(oNewLis);

        // 存放被拖动的对象
        var dragObj = null;

        // 拖过来
        for(let i = 0,len = oLis.length; i < len; i++){
            oLis[i].ondragstart = function(){
                dragObj = this;
            }
        }
        oNewUl.ondragover = function(e){
            e.preventDefault();
        }
        oNewUl.ondrop = function(){
            this.appendChild(dragObj);
        }

        // 拖回去

        for(let i = 0,len = oNewLis.length; i < len; i++){
            oNewLis[i].ondragstart = function(){
                dragObj = this;
            }
        }

        oUl.ondragover = function(e){
            e.preventDefault();
        }
        oUl.ondrop = function(e){
           this.appendChild(dragObj);
        }

4.jpg

点击图片查看效果。

1.4、DataTransfer 对象

DataTransfer 对象用于保存拖动并放下(drag and drop)过程中的数据。它可以保存一项或多项数据,这些数据项可以是一种或者多种数据类型。

通过event.dataTransfter访问该对象。

该对象下面的常用方法:

方法功能
setData(format, data)

设置给定类型的数据。如果该类型的数据不存在,则将其添加到末尾,如果该类型的数据已经存在,则在相同位置替换现有数据。

event.dataTransfer.setData(format, data)

setDragImage(img, xOffset, yOffset)

发生拖动时,从拖动目标生成半透明图像,并在拖动过程中跟随鼠标指针。这个图片是自动创建的,你不需要自己去创建它。如果想要设置为自定义图像,那么 DataTransfer.setDragImage() 方法就能派上用场。图像通常是一个 img 元素,但也可以是canvas 或任何其他图像元素。该方法的x和y坐标是图像应该相对于鼠标指针出现的偏移量。要使图像居中,请使用图像宽度和高度的一半。

event.dataTransfer.setDragImage(img, xOffset, yOffset);

clearData([format])

删除给定类型的拖动操作的drag data。如果给定类型的数据不存在,则此方法不执行任何操作。如果没有参数,或者格式为空 ,则将删除所有类型的数据。

event.dataTransfer.clearData([format]);

getData(format)接受指定类型的拖放数据。如果拖放行为没有操作任何数据,会返回一个空字符串。

dataTransfer常用属性:

属性含义
files

在拖动操作中表示[文件列表]。如果操作不包含文件,则此列表为空。此功能可用于将文件从用户桌面拖动到浏览器。

ev.dataTransfer.files  如果有文件,则返回一个FileList对象。

1.5、拖拽删除案例

点击查看案例

具体代码如下:

    <div class="wrapper">
        <div class="dustbin">垃圾箱</div>
        <div class="dustbox">
            <div class="dustitem" draggable="true">列表项1</div>
            <div class="dustitem" draggable="true">列表项2</div>
            <div class="dustitem" draggable="true">列表项3</div>
            <div class="dustitem" draggable="true">列表项4</div>
            <div class="dustitem" draggable="true">列表项5</div>
        </div>
       
    </div>
    <p class="tips"></p>
    
    <script>
        const oDustbin = document.querySelector('.dustbin');
        const oDustitem = document.querySelectorAll('.dustitem');
        const oP = document.querySelector('.tips');
        // 设置被拖动对象
        var dragObj = null;
        for(let i = 0, len = oDustitem.length; i < len ; i++){
            oDustitem[i].ondragstart = function(e){
                // 把当前对象保存在被拖动对象的变量中
                dragObj = this;
                console.log(dragObj);
                // 绑定数据进行传输
                e.dataTransfer.setData('text',e.target.innerHTML);
                // 创建一个图片对象
                // const oImg = document.createElement('img');
                const oImg = new Image();
                oImg.src = 'images/email.png';
                // 拖动的时候显示图片,而不是原始的对象。
                e.dataTransfer.setDragImage(oImg,0,0);
                // e.dataTransfer.setDragImage(e.target,0,0);
                console.log(e.dataTransfer);

            }
            // 在中途释放,则清除数据,清空被拖动对象变量。
            oDustitem[i].ondragend = function(e){
                e.dataTransfer.clearData('text');
                dragObj = null;
            }
        }

        // 目标元素的文本发生变化
        oDustbin.ondragenter = function(){
            this.style.color= '#fff';
        }
        oDustbin.ondragleave = function(){
            this.style.color= '#000';
        }
        // 阻止默认行为,才能触发ondrop事件
        oDustbin.ondragover = function(e){
            e.preventDefault();
        }
        // 如果被拖动元素变量有值,则删除该元素
        oDustbin.ondrop = function(e){
            dragObj && dragObj.remove();
            // 获取传递过来的数据并显示。
            let val = e.dataTransfer.getData('text');
            oP.innerHTML = val +'被删除了';
        }
    </script>


二、FileList

一个 FileList 对象通常来自于一个 HTML input 元素的 files 属性,你可以通过这个对象访问到用户所选择的文件。该类型的对象还有可能来自用户的拖放操作 。

所有type属性(attribute)为file的 input 元素都有一个files属性(property),用来存储用户所选择的文件。

<input id="fileItem" type="file">
<script>
    //获取到一个FileList对象中的第一个文件
var file = document.getElementById('fileItem').files[0];
</script>
<input type="file" multiple id="files">

<script>

    var oFiles = document.querySelector('#files');

    // 当值发生改变的时候
    oFiles.onchange = function(){
        // 获取所有选中的文件
        var filelist = oFiles.files;
        // console.log(filelist);
        for(var i = 0 ; i < filelist.length; i++){
            // 获取每个文件的名字和尺寸,默认是字节byte 1kb = 1024b
            console.log(filelist[i].name,filelist[i].size / 1024);
        }

    }
</script>

三、FileReader

https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader

FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件的内容,使用 File 对象指定要读取的文件或数据。

3.1、创建一个实例对象

var filereader = new FileReader();

3.2、方法

instanceOfFileReader.readAsDataURL(file);

readAsDataURL 方法会读取指定的file对象, 读取操作完成的时候,  readyState 会变成已完成DONE,并触发 loadend (en-US) 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。

Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。采用Base64编码具有不可读性,需要解码后才能阅读。

图片 base64 的目的不是减小其大小,而是嵌入在网页中,以此避免浏览器再去对图片发送另一个单独的请求的开销。

使用base64保存图片并不是为了节省存储空间,而是为了减少请求.要知道请求耗时且费服务器.如果一个H5页面包含有100张图片,那么用户打开一次,至少要请求100次图片,1次html文件,css文件和js文件都要请求.这么下来,如果1000人同时打开,服务器就瞬间达到了1000*101次100000并发量,无形之中增加了服务器巨大的成本.而使用base64,把图片数据全部存在一个js文件中,一次请求就2次,一个html文件和一个images.js文件.服务器1000人同时并发也就2000量级.减少服务器压力.

 base64 编码过程:对二进制数据进行处理,每 3 个字节一组,一组就是 3 * 8 = 24 位,再分为 4 组,每组就是 6 位,这样每组就刚好可以用一个 base64 可打印字符来表示,一共 4 组。这样原来的 3 个字节进过编码后会变成 4 个字节。文件大约变大(长) 1/3  ,所以 base64编码前和编码后大概是3:4的比例 。

3.3、事件

onload事件

当文件读取完毕后,会触发该事件。

3.4、 属性

result属性

返回文件的内容。只有在读取操作完成后,此属性才有效,返回的数据的格式取决于是使用哪种读取方法来执行读取操作的。

显示上传文件的缩略图:

    <input type="file"  id="files">
    <img src="" alt="" id="slt">

    <script>
    
        var oFiles = document.querySelector('#files');
        var oImg = document.querySelector('#slt');

        // 当值发生改变的时候
        oFiles.onchange = function(){
            // 获取选中的文件
            var file = oFiles.files[0];
           // 创建读取文件对象的实例
            var freader = new FileReader();
            // 如果文件存在
            if(file){
                // 开始读取文件,以base64的编码方式读取。
                freader.readAsDataURL(file);
            }
            // 读取完成之后,把结果显示出来
            freader.onload = function(e){
                // console.log(e.target.result);
                oImg.src = freader.result;
            }
        }
    </script>

点击查看具体效果,选择一张你电脑上的图片上传,可以看到在网页上显示这张图片。


点击可以查看一个比较完整的拖拽上传案例。

5.jpg


点赞


1
保存到:

相关文章

发表评论:

◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。

Top