<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>文件上传</title>
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 500px;
min-height: 500px;
margin: 50px auto;
padding-top: 30px;
background-color: rgb(248 248 248);
border-radius: 10px;
}
.btn {
width: 200px;
height: 30px;
line-height: 30px;
margin: 10px auto;
text-align: center;
color: #5098f8;
border-radius: 4px;
border: 1px dashed #5098f8;
cursor: pointer;
}
ul li {
list-style: none;
border: 1px solid rgb(232 232 232);
border-radius: 4px;
margin-bottom: 10px;
cursor: pointer;
min-height: 54px;
line-height: 54px;
display: flex;
justify-content: space-between;
width: 500px;
}
#drop {
width: 500px;
height: 100px;
color: #5098f8;
border-radius: 4px;
border: 1px dashed #5098f8;
display: none;
/* transform: scale(1.1); */
position: absolute;
}
ul li p {
display: none;
line-height: 54px;
}
#wmList {
width: 600px;
}
</style>
</head>
<body>
<!-- 这个id属性放在哪个盒子里面 哪个盒子的范围就是拖拽上传的范围 -->
<div class="box" id="drapBox">
<!-- 用来展示的上传按钮 -->
<div class="btn" id="btn">点击上传按钮</div>
<div id="drop"></div>
<ul id="ulList"></ul>
<!-- 实际实现上传的input 并限制文件类型(不保险,因为用户可以放手放开限制,选择所有类型文件,所以需要在上传之前进行第二次验证) -->
<input
type="file"
id="file-btn"
οnchange="selectFile(event)"
multiple="multiple"
style="display: none"
/>
</div>
<script src="./lib/draggable-polyfill.js"></script>
<script>
let file = null; // 要进行上传的文件
// 给上传按钮绑定点击事件
let ulList = document.querySelector("#ulList");
document.querySelector("#btn").onclick = function () {
// 模拟点击上传的input 弹出文件选择框
document.querySelector("#file-btn").click();
};
let liMouse = document.getElementsByTagName("p");
let fileList = [];
//拖拽
let res = [
{
name: "ICBCSTL-76411-ICBCSTL-76238【2023055】集管会刚控软需项目设计文档(1).docx",
},
{
name: "GoRes 1.4.0.crx",
},
];
fileList = res;
copyList(fileList);
// 获取点击上传 选择的文件
function selectFile(e) {
// 通过 e.target.files 获取到选择的文件 此处默认选择一个文件
for (let index = 0; index < e.target.files.length; index++) {
fileList.push(e.target.files[index]);
}
const newArr = unique(fileList, "name");
fileList = newArr;
copyList(fileList);
}
// 拖拽上传获取对应文件
let drapId = document.querySelector("#drapBox");
let dropBox = document.querySelector("#drop");
// 当文件在目标元素内移动时
window.addEventListener("dragover", function (e) {
let target = e.target;
let closestTip = target.closest("#drapBox");
if (!closestTip) {
dropBox.style.display = "block";
}
e.stopPropagation();
// 阻止默认事件(与drop事件结合,阻止拖拽文件在浏览器打开的默认行为)
e.preventDefault();
});
// // 当拖拽文件在目标元素内松开时
window.addEventListener("drop", function (e) {
// 阻止事件冒泡
e.stopPropagation();
// 阻止默认事件(与dragover事件结合,阻止拖拽文件在浏览器打开的默认行为)
e.preventDefault();
let target = e.target;
let closestTip = target.closest("#drapBox");
if (closestTip) {
dropBox.style.display = "none";
// 获取拖拽上传的文件
for (let index = 0; index < e.dataTransfer.files.length; index++) {
fileList.push(e.dataTransfer.files[index]);
}
const newArr = unique(fileList, "name");
fileList = newArr;
copyList(fileList);
}
});
//删除
function handleClick(index) {
fileList.splice(index, 1);
copyList(fileList);
}
//去重
function unique(arr, key) {
const map = new Map();
return arr.filter((item) => {
const k = item[key];
if (map.has(k)) {
console.log("重复了!!");
return false;
} else {
map.set(k, true);
return true;
}
});
}
//动态添加
function copyList(list) {
let liElements = document.querySelectorAll("li");
for (let i = 0; i < liElements.length; i++) {
liElements[i].parentNode.removeChild(liElements[i]);
}
for (let index = 0; index < list.length; index++) {
let newLi = document.createElement("li");
let newSpan = document.createElement("span");
newSpan.textContent = fileList[index].name;
newLi.setAttribute("class", "lit");
newLi.setAttribute("draggable", "true");
let newP = document.createElement("p");
newP.textContent = "X";
ulList.append(newLi);
newLi.append(newSpan);
newLi.append(newP);
let formdata = new FormData();
formdata.append("file", fileList[index]);
file = formdata;
newP.addEventListener("click", function () {
handleClick(index);
});
drap();
}
}
function drap() {
let lit = document.getElementsByClassName("lit");
let con = null;
let spanCon = null;
let spanConTwo = null;
for (let i = 0; i < lit.length; i++) {
//拖动时,用con保存lit
lit[i].onmouseover = function () {
this.querySelector("p").style.display = "block";
this.querySelector("p").onmouseover = function () {
this.style.color = "rgb(232 232 232)";
};
this.querySelector("p").onmouseout = function () {
this.style.color = "black";
};
};
lit[i].onmouseout = function () {
this.querySelector("p").style.display = "none";
};
lit[i].ondragstart = function (e) {
con = this;
spanCon = this.querySelector("span").innerHTML;
};
lit[i].ondragover = function (e) {
event.preventDefault();
window.addEventListener("dragover", function (e) {
let target = e.target;
let closestTip = target.closest("#drapBox");
if (!closestTip) {
dropBox.style.display = "none";
}
});
};
//拖动结束时,在当前位置下 进行drop事件
lit[i].ondrop = function () {
if (con != null && con != this) {
spanConTwo = this.querySelector("span").innerHTML;
let abc = document.createElement("li");
ulList.replaceChild(abc, this);
ulList.replaceChild(this, con);
ulList.replaceChild(con, abc);
let index1 = fileList.findIndex((item) => item.name == spanCon); // 要交换的第一个元素的索引
let index2 = fileList.findIndex(
(item) => item.name == spanConTwo
); // 要交换的第二个元素的索引
fileList.splice(
index2,
1,
...fileList.splice(index1, 1, fileList[index2])
);
copyList(fileList);
}
};
}
}
</script>
</body>
</html>
//优化拖拽
/**
* @description draggable polyfill
* @author XboxYan
* @email yanwenbin1991@live.com
* @github https://github.com/XboxYan/draggable-polyfill
* @license MIT
*/
/**
* draggable polyfill
*/
(function () {
if ("setDragImage" in window.DataTransfer.prototype && document.body.animate) {
var cloneObj = null;
var offsetX = 0;
var offsetY = 0;
var startX = 0;
var startY = 0;
var dragbox = null;
var lastDrop = null;
var axis,_axis;
var previewImage = new Image();
previewImage.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAQSURBVHgBAQUA+v8AAAAAAAAFAAFkeJU4AAAAAElFTkSuQmCC";
var styles = document.createElement("style");
styles.textContent = '[dragging]{position:static!important;box-sizing:border-box!important;margin:0!important;}\
.drag-obj{position:fixed;left:0;top:0;z-index:999;pointer-events:none;}'
document.querySelector('head').appendChild(styles);
document.addEventListener('dragstart', function (ev) {
if (ev.target.nodeType === Node.ELEMENT_NODE) {
dragbox = ev.target;
dragbox.dragData = {};
axis = dragbox.getAttribute('axis');
_axis = axis;
ev.dataTransfer.setData('text','');
ev.dataTransfer.setDragImage(previewImage, 0, 0);
var rect = dragbox.getBoundingClientRect();
var left = rect.left;
var top = rect.top;
startX = ev.clientX;
startY = ev.clientY;
offsetX = startX - left;
offsetY = startY - top;
dragbox.style.transition = 'none';
cloneObj = document.createElement('DIV');
var fakeObj = dragbox.cloneNode(true);
fakeObj.style.width = dragbox.offsetWidth+'px';
fakeObj.style.height = dragbox.offsetHeight+'px';
fakeObj.style.transform = 'translate3d(0,0,0)';
fakeObj.style.listStyle ='none'
fakeObj.setAttribute('dragging', '');
cloneObj.appendChild(fakeObj);
cloneObj.className = 'drag-obj';
cloneObj.style = 'transform:translate3d( ' + left + 'px ,' + top + 'px,0);';
document.body.appendChild(cloneObj);
}
})
document.addEventListener('dragend', function (ev) {
if(cloneObj){
var rect = ev.target.getBoundingClientRect();
var left = rect.left;
var top = rect.top;
var reset = cloneObj.animate(
[
{ transform: cloneObj.style.transform},
{ transform: 'translate3d('+left+'px,'+top+'px,0)' }
],
{
duration: 150,
easing:"ease-in-out",
}
)
reset.onfinish = function(){
document.body.removeChild(cloneObj);
cloneObj = null;
dragbox.dragData = null;
dragbox.style.visibility = 'visible';
}
}
})
document.addEventListener('drop', function(ev) {
const dropbox = ev.target.closest('[allowdrop]');
ev.preventDefault();
if (dropbox) {
ev.stopPropagation();
dropbox.removeAttribute('over');
}
})
document.addEventListener('dragenter', function(ev) {
if (lastDrop) {
lastDrop.toggleAttribute('over',false);
}
const dropbox = ev.target.closest('[allowdrop]'); // 获取最近的放置目标
if (dropbox) {
dropbox.toggleAttribute('over',true);
lastDrop = dropbox;
}
})
document.addEventListener('dragover', function (ev) {
ev.preventDefault();
const dropbox = ev.target.closest('[allowdrop]');
if (dropbox) {
ev.dataTransfer.dropEffect = 'copy';
} else {
ev.dataTransfer.dropEffect = 'move';
}
if (cloneObj) {
dragbox.style.visibility = 'hidden';
var left = ~~(ev.clientX - offsetX);
var top = ~~(ev.clientY - offsetY);
if(ev.shiftKey || axis ){
if(_axis==='X'){
top = ~~(startY - offsetY);
}else if(_axis==='Y'){
left = ~~(startX - offsetX);
}else{
_axis = ~~Math.abs(ev.clientX-startX)>~~Math.abs(ev.clientY-startY) && 'X' || ~~Math.abs(ev.clientX-startX)<~~Math.abs(ev.clientY-startY) && 'Y' || '';
}
}else{
_axis = '';
}
startX = left + offsetX;
startY = top + offsetY;
cloneObj.style.transform = 'translate3d( ' + left + 'px ,' + top + 'px,0)';
dragbox.dragData.left = left;
dragbox.dragData.top = top;
}
})
}
})();