HTML5拖拽事件
1. h5拖拽和js拖拽
-
JS里拖拽三事件:mousedown、mousemove、mouseup
实现交互性效果,根据鼠标的移动的位置让元素联动dv.addEventListener('mousedown', function (e) { let x = e.clientX - this.offsetLeft let y = e.clientY - this.offsetTop function handleMove(ev) { dv.style.cssText = `left: ${ev.clientX - x}px; top: ${ ev.clientY - y }px;` } function handleUp(ev) { this.removeEventListener('mousemove', handleMove) this.removeEventListener('mouseup', handleUp) } document.addEventListener('mousemove', handleMove) document.addEventListener('mouseup', handleUp) })
-
H5拖拽也可以实现,而且更简单,实际例子:百度图片识别、qq邮箱文件提交、百度网盘文件上传,并且能获取到文件的名称、大小、修改事件
dv.addEventListener('dragstart', function (e) { let x = e.clientX - this.offsetLeft let y = e.clientY - this.offsetTop this.addEventListener('dragend', function (ev) { this.style.cssText = `left: ${ev.clientX - x}px; top: ${ ev.clientY - y }px;` }) })
2. 拖拽七事件
- 除图片外的标签元素默认是不可以拖拽的,加上
draggable="true"
才能被拖拽 - 拖拽七事件
- dragstart 拖拽开始,拖拽前触发 ,事件只触发一次
- drag 拖拽中,拖拽前、拖拽结束之间,连续触发
- dragend 拖拽结束,拖拽结束触发 ,事件只触发一次
- dragenter 拖拽进入目标触发
- dragover 在目标元素上,进入目标、离开目标之间,连续触发
- dragleave 离开目标元素触发
- drop 在目标元素释放鼠标触发
2.1. 拖拽元素(被拖拽元素对象)事件 :
const box = document.getElementById('box');
// dragstart 拖拽开始时触发,只触发一次
box.ondragstart = function () {
this.style.background = 'blue';
}
// drag拖拽触发的事件,连续触发,只要鼠标不松开会一直触发
box.ondrag = function () {
this.style.background = 'yellow';
}
// dragend 拖拽结束时,触发的事件,只要鼠标一松开就触发
box.ondragend = function () {
this.style.background = 'skyblue';
}
2.2. 目标元素(拖拽元素被拖到的对象)事件 :
// dragenter 拖拽元素移入目标元素时触发,鼠标进入才算哦
wrap.ondragenter = function () {
this.innerHTML = '释放鼠标';
}
// dragove 拖拽的元素在目标元素中触发,会连续触发
wrap.ondragover = function (e) {
this.style.background = '#999';
console.log(num++);
// e.preventDefault();
return false;
}
// dragleave 拖拽的元素离开目标元素时触发,鼠标离开才算
wrap.ondragleave = function () {
this.innerHTML = '请将元素拖进来';
}
// drop 在目标元素中松口鼠标触发,如果要触发这个事件,必须先将drapover事件取消默认事件
wrap.ondrop = function () {
this.style.background = 'skyblue';
console.log('你在目标元素中松口了鼠标');
document.body.removeChild(box);
}
回收站拖拽删除
2. 拖拽兼容问题
只作为了解, 因为现在火狐已经没有兼容问题
火狐浏览器下需设置dataTransfer对象才可以拖拽除图片外的其他标签
火狐在没有添加dataTransfer前不能使用ondrag和ondragend事件,其他都可以
2.1. dataTransfer对象
dataTransfer 是 拖拽事件对象的属性
-
setData() : 设置数据 key和value(必须是字符串)
-
getData() : 获取数据,根据key值,获取对应的value
let right = document.querySelector('#right'); let lis = right.querySelectorAll('li'); console.log(lis); lis.forEach(function (li, index) { li.setAttribute('draggable', true); li.addEventListener('dragstart', function (e) { // 设置携带数据 e.dataTransfer.setData('foo', index); }); }); let left = document.querySelector('#left'); left.addEventListener( 'dragover', function (e) { e.preventDefault(); }, { passive: false } ); left.addEventListener('drop', function (e) { const index = e.dataTransfer.getData('foo'); right.removeChild(lis[index]); });
-
setDragImage :三个参数(指定的元素,坐标X,坐标Y)
box.ondragstart = function (e) { console.log(e.dataTransfer); e.dataTransfer.setDragImage(img, 100, 100); }
-
files: 获 取外部拖拽的文件,返回一个filesList列表
filesList下有个type属性,返回文件的类型wrap.ondrop = function (e) { const dt = e.dataTransfer; console.log(dt.files) console.log( dt.files[0].name, dt.files[0].type, dt.files[0].lastModified, dt.files[0].lastModifiedDate.toLocaleDateString(), dt.files[0].lastModifiedDate.toLocaleTimeString(), dt.files[0].lastModifiedDate.toDateString(), ); return false; }
3. 读取读取文件信息
3.1Blob读取文件对象
Blob对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或者二进制格式进行读取。
- Blob,Binary Large Object 的缩写,代表二进制类型的大对象,提供了一系列接口
- MySQL中也有Blob类型,表示的是二进制数据容器
- File类型的接口基于Blob类型
- 构造函数
Blob(array[, options])
URL对象
URL.createObjectURL()
返回指定对象的URL,该URL的生命周期与创建它的窗口对象document绑定。该URL对象表示指定的File或者Blob对象
const oFile = e.dataTransfer.files.item(0); // 拿到第一个文件
if (/image/.test(oFile.type)) { // 判断文件类型
let url = window.URL.createObjectURL(oFile); // 可以传入 File类型 或者 Blob类型
console.log(url)
let img = new Image();
img.width = 100;
img.src = url;
img.onload = function () {
box.appendChild(this);
};
}
3.2 FileReader(读取文件信息)
FileReader类型实现了一种异步文件读取机制。可以把FileReader想象成XMLHttpRequest,区别在于,它只读取文件系统,而不是远程服务器。
- 方法:
-
readAsText(file, encoding)
:以纯文本形式读取文件,将读取到的文本保存在result
属性中 -
readAsDataURL(file)
:读取文件并将文件以URI的形式保存在result
属性中 -
readAsBinaryString(file)
:读取文件并将一个字符串保存在result
属性 -
readAsArrayBuffer(file)
:读取文件,并将一个包含文件内容的ArrayBuffer保存在result
属性
-
- 事件:
- progress 每 50ms触发一次
- error 读取出错时触发
- load 成功加载后触发
wrap.ondrop = function (e) {
const dt = e.dataTransfer;
const oFile = dt.files.item(0);
// 创建读取文件对象
const file = new FileReader();
// 获取文件的url
file.readAsDataURL(oFile)
// 当信息读取完成后执行
file.onload = function () {
// console.log(oFile);
if (oFile.type.includes('image')) {
const img = new Image();
img.src = file.result;
wrap.appendChild(img)
}
}
return false;
}
性能低,没有必要吧这些字符串渲染到页面中
3.2 异步文件上传
FormData对象
FormData提供了一种表示表单数据的键值对构造方式,可以轻松将数据通过XMLHttpRequest.send()
方法发送出去。
- 方法
-
append(name, value)
向FormData中添加新的属性值,FormData中对应的属性值存在也不会覆盖原来的值,而是新增一个值,如果属性不存在则新增一项属性值 -
delete(name)
从FromData中删除一个键值对 -
get(name)
获取指定键的第一个值,想要获取全部值可以用getAll(name)
-
set(name, value)
与append区别在于,会覆盖
-
const xhr = new XMLHttpRequest();
xhr.onload = function () {
console.log('aaa')
console.log(xhr.responseText);
};
xhr.open(
'post',
'http://www.tanzhouweb.com/h5upload/upload.php',
true
);
// 通过表单对象 携带数据
const fd = new FormData();
fd.append('file', file);
xhr.send(fd);
}