早期拖拽的实现很麻烦,需要利用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); }
点击图片查看效果。
1.4、DataTransfer 对象
DataTransfer
对象用于保存拖动并放下(drag and drop)过程中的数据。它可以保存一项或多项数据,这些数据项可以是一种或者多种数据类型。
通过event.dataTransfter访问该对象。
该对象下面的常用方法:
方法 | 功能 |
setData(format, data) | 设置给定类型的数据。如果该类型的数据不存在,则将其添加到末尾,如果该类型的数据已经存在,则在相同位置替换现有数据。 event.dataTransfer.setData(format, data) |
setDragImage(img, xOffset, yOffset) | 发生拖动时,从拖动目标生成半透明图像,并在拖动过程中跟随鼠标指针。这个图片是自动创建的,你不需要自己去创建它。如果想要设置为自定义图像,那么 event.dataTransfer.setDragImage(img, xOffset, yOffset); |
clearData([format]) | 删除给定类型的拖动操作的 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>
点击查看具体效果,选择一张你电脑上的图片上传,可以看到在网页上显示这张图片。
点击可以查看一个比较完整的拖拽上传案例。
发表评论:
◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。