早期拖拽的实现很麻烦,需要利用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>点击查看具体效果,选择一张你电脑上的图片上传,可以看到在网页上显示这张图片。
点击可以查看一个比较完整的拖拽上传案例。


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