必须先引入 Jquery 依赖

1.文件结构

2. HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>拖拽</title>
<link rel="stylesheet" type="text/css" href="./css/index.css" />
<script src="./js/jquery-3.5.1.min.js"></script>
<script src="./js/index.js"></script>
</head>
<body>
<!-- 触发按钮 -->
<button type="button" id="clickBtn" class="clickBtn">点击选择</button>
<!-- 拖拽盒子 -->
<div id="select_file_div"class="select_file_div">
<div id="drag_file_div"class="drag_file_div"contenteditable="true">
<p class="drag_file_div_p"contenteditable="false">请选择或拖拽文件至此区域</p>
</div>
<div id="drag_file_control"class="drag_file_control noSelect">
<p>暂未选择文件</p><span>按住任意拖动</span>
<div id="drag_file_cancel"class="drag_file_cancel">完成</div><a
href="javascript:void(0);"id="select_file_a"class="select_file_a"><input
type="file"multiple="true"id="select_file_addFile"class="select_file_addFile">手动选择</a>
</div>
</div>
</body>
</html>

3. CSS

*{margin:0;padding:0;box-sizing:border-box}.clickBtn{width:148px;height:48px;letter-spacing:4px;font-size:16px;margin:16px 0 0 16px}.tip{width:auto;min-width:168px;height:60px;position:fixed;left:44%;z-index:199;padding:0 8px 0 8px;line-height:60px;text-align:center;font-size:18px;border-radius:4px;box-shadow:#393D49 2px 2px 8px;background-color:#1E9FFF;color:#ffffff;animation:tip 0.3s;animation-fill-mode:forwards;-webkit-animation-fill-mode:forwards}@keyframes tip{from{top:0px}to{top:80px}}@-webkit-keyframes tip{from{top:0px}to{top:80px}}.tipKill{animation:tipKill 1s;animation-fill-mode:forwards;-webkit-animation-fill-mode:forwards}@keyframes tipKill{from{top:80px}to{background-color:rgba(0,0,0,0);box-shadow:rgba(0,0,0,0) 2px 2px 8px;color:rgba(0,0,0,0);top:0px}}@-webkit-keyframes tipKill{from{top:80px}to{background-color:rgba(0,0,0,0);box-shadow:rgba(0,0,0,0) 2px 2px 8px;color:rgba(0,0,0,0);top:0px}}.noSelect{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.select_file_div{display:none;width:650px;position:fixed;top:20%;left:32%;z-index:101}.drag_file_div{width:100%;height:340px;padding:3px;background:url("../img/b2.jpg");background-size:100%;border:1px solid #4b4b4b;box-shadow:inset 0 1px 1px #d6d6d6;outline:medium;font-size:14px}.drag_file_div>p{position:absolute;width:240px;height:50px;text-align:center;left:0;top:0;right:0;bottom:0;margin:auto;border:1px dashed #ddd;font-size:1em;color:#999;display:block;line-height:50px}.drag_file_selectfile{width:98%;height:38px;margin:8px 1%;line-height:38px;color:#bfbfbf;background-color:#393D49;box-shadow:1px 1px 1px #ffffff}.drag_file_selectfile:hover{color:#eeeeee;box-shadow:2px 2px 4px #ffffff}.drag_file_selectfile>div{float:left}.drag_file_selectfile .select_filename{width:388px;height:38px;margin-left:10px}.drag_file_selectfile .select_filesize{width:168px;margin-left:10px}.drag_file_selectfile .select_file_clear{display:block;width:20px;height:20px;margin:9px;background:url("../img/delete1.png");background-size:100%;cursor:pointer}.drag_file_selectfile .select_file_clear:hover{background:url("../img/delete2.png");background-size:100%}.drag_file_selectfile>div>span:nth-child(1){font-weight:700;margin:0 6px 0 0}.drag_file_control{width:650px;margin:0 auto;height:45px;line-height:45px;background:#393D49;border-width:0 1px 1px 1px;border-style:solid;border-color:#747474;cursor:pointer}.drag_file_control .select_file_a{position:relative;width:92px;height:34px;line-height:34px;text-decoration:none;color:#ffffff;font-size:14px;letter-spacing:2px;cursor:pointer;background:#89a3b3;border-radius:3px;overflow:hidden;text-align:center;float:right;margin:5px 8px 5px}.drag_file_control .select_file_a>input{position:absolute;width:92px;height:34px;right:0;top:0;opacity:0;cursor:pointer}.select_file_addFile{display:block;margin:0 auto;text-align:center;font-size:14px;cursor:pointer}.drag_file_control>p{width:158px;color:#d9d9d9;float:left;font-size:14px;padding-left:20px}.drag_file_control>span{margin:0 0 0 24px;color:#666;font-size:14px}.dragOver{box-shadow:inset 1px 1px 2px rgba(0,0,0,.5) !important}.drag_file_cancel{width:92px;height:34px;background:#1c8fe5;color:#eeeeee;font-size:14px;letter-spacing:4px;border-radius:3px;display:block;line-height:34px;text-align:center;cursor:pointer;float:right;margin:5px 8px 5px}.select_file_a:hover,.drag_file_cancel:hover{opacity:0.6}

4. JS

var selectFileArr = new FormData(); // 选中文件
var selectFileArrKey = []; // 选中文件名集合
var selectFileSizeSum = 0; // 选中文件总大小
var maxFileNum = 1; // 选择文件数量上限
var maxFileSize = 100; // 选择文件大小上限(单位Mb)
var sheetErrorData = {}; // 导入失败数据
var canFileType = ['.xlsx']; // 允许的文件类型
var dragFileDiv = null; // 显示对象_主体盒子
var dragFileTip = null; // 显示对象_提示内容 var errTip = {'background-color': '#ff6528', 'color': '#eeeeee', 'font-weight': '700'}; $(function() {
// 拖拽移动
dragMove('#select_file_div', false); // 点击选择文件
$('#clickBtn').click(function() {
var parameter = {
maxFileNum: 7,
maxFileSize: 100
}
dragSelectFileLoad(parameter); // 加载
});
}); /**
* 加载函数
* @param parameter JSON参数对象
*/
function dragSelectFileLoad(parameter) {
$('body')[0].contentEditable = false; // 规定元素内容是否可编辑
$('#select_file_div').show(); // 显示盒子
maxFileNum = parameter.maxFileNum || 1; // 最多可选取文件数
maxFileSize = parameter.maxFileSize || 1; // 选择文件大小上限(单位Mb)
// 显示对象
dragFileDiv = $('#drag_file_div')[0];
dragFileTip = $('.drag_file_div_p');
// 鼠标拖入时
dragFileDiv.ondragenter = function(ev) {
dragFile.evStop(ev);
dragFileTip.text('请释放鼠标');
$(this).addClass('dragOver');
}
// 移出
dragFileDiv.ondragleave = function(ev) {
dragFile.evStop(ev);
dragFileTip.text('请添加或拖拽文件至此区域');
$(this).removeClass('dragOver');
}
// 释放元素
dragFileDiv.ondrop = function(ev) {
dragFile.evStop(ev);
this.setAttribute('contenteditable', 'false'); // 不可再拖动
dragFile.readFile(ev);
}
// 选择文件后
$('#select_file_addFile').change(function() {
dragFile.addCheck($('#select_file_addFile')[0].files[0]); // 文件校验
});
// 取消按钮
$('#drag_file_cancel').click(function() {
$('#select_file_div').hide();
});
} /**
* 拖拽文件操作对象
*/
var dragFile = {
// 读取拖拽文件
readFile: function(ev) {
var File = ev.dataTransfer.files;
for (var i = 0; i < File.length; i++) {
dragFile.addCheck(File[i]);
}
},
// 文件格式验证
addCheck: function(file) {
var fnLast = file.name.substr(file.name.lastIndexOf('.'));
if (!isNull(file.name) && canFileType.indexOf(fnLast) != -1) { // 文件类型校验
// console.log(selectFileArrKey.length, maxFileNum);
if (selectFileArrKey.length < maxFileNum && maxFileNum > 0) { // 文件数量限制
if (!selectFileArr.has(file.name)) { // 文件名未重复
var fileSize = file.size / 1048576;
if (selectFileSizeSum + file.size < maxFileSize * 1048576) { // 总文件大小限制
selectFileSizeSum += file.size; // 记录文件总大小
dragFile.addFile(file, fileSize.toFixed(2)); // 添加文件
} else {
tip('文件大小不能超过 ' + maxFileSize + ' MB', 1200, errTip);
}
} else {
tip('文件名重复', 1200, errTip);
}
} else {
tip('最多可选择 ' + maxFileNum + ' 个文件', 1200, errTip);
}
} else {
tip('不支持的文件格式', 1200, errTip);
}
},
// 列表显示
addFile: function(file, fileSize) {
var fileName = file.name; // 文件名
var showFileName = file.name; // 显示文件名
var tpFl = fileName.substr(fileName.lastIndexOf('.')); // 后缀
if (fileName.length > 16 + tpFl.length) { // 超过长度则截取
showFileName = fileName.substring(0, 16) + '……' + tpFl;
}
selectFileArr.append(file.name, file); // 添加文件
selectFileArrKey.push(file.name); // 记录文件名
dragFileTip.hide(); // 隐藏提示文字
updateShowFileName(); // 更新显示
var str = "<div class=\"drag_file_selectfile\" contenteditable=\"false\">" +
"<div class=\"select_filename\"><span>文件名</span>" + showFileName + "</div>" +
"<div class=\"select_filesize\"><span>文件大小:</span>" + fileSize + 'MB' + "</div>" +
"<div class='select_file_clear' onclick=\"dragFile.removeFile('" + fileName + "', this)\"></div></div>";
$('#drag_file_div').append(str);
},
// 移除文件
removeFile: function(fileName, that) {
fileName = fileName.trim();
if (selectFileArr.has(fileName)) {
selectFileArr.delete(fileName); // 移除数据
$(that).parent().remove(); // 找到父元素并删除
// 去除删除元素Key
var tpSfakArr = [];
for (let k in selectFileArrKey) {
if (selectFileArrKey[k] != fileName)
tpSfakArr.push(selectFileArrKey[k]);
}
selectFileArrKey = tpSfakArr;
updateShowFileName(); // 更新显示
tip('文件 【 ' + fileName + ' 】 移除成功', 2000, {});
}
if (selectFileArrKey.length <= 0) {
$('.drag_file_div_p').show(); // 显示提示文字
}
},
// Url事件截停
evStop: function(e) {
var ev = e || window.event;
ev.preventDefault();
ev.stopPropagation(); // Fiefox兼容
},
// 重置
reset: function() {
selectFileArr = new FormData(); // 选中文件数
selectFileArrKey = []; // 选中文件数
dragFileDiv = null; // 显示对象_主体盒子
dragFileTip = null; // 显示对象_提示内容
$('#select_file_addFile').reset();
}
} /**
* 更新文件名显示
*/
function updateShowFileName() {
if (selectFileArrKey.length > 0) {
// var fileSpanFileName = selectFileArrKey.join(' / ');
// $('#file_span').text(fileSpanFileName.length <= 24 ? fileSpanFileName : fileSpanFileName.substring(0, 24) + ' ……');
$('#drag_file_control>p').text('选择了' + selectFileArrKey.length + '个文件'); // 添加显示
} else {
// $('#file_span').text('暂未选择文件');
$('#drag_file_control>p').text('暂未选择文件'); // 添加显示
$('#drag_file_div>div').remove();
$('.drag_file_div_p').show(); // 显示提示文字
}
} /**
* 拖拽移动
* @param obj 目标对象 / #id / .class
* @param moveOut 是否可以移出边界
*/
function dragMove(dom, moveOut) {
var obj = $(dom);
moveOut = moveOut || false;
obj.bind('mousedown', start);
var deltaX = 0,
deltaY = 0; function start(e) {
var ol = obj.offset().left;
var ot = obj.offset().top;
deltaX = e.pageX - ol;
deltaY = e.pageY - ot;
$(document).bind({
'mousemove': move,
'mouseup': stop
});
return false;
} function move(e) {
var tpX = 0,
tpY = 0;
if ((e.pageX - deltaX > 0 && e.pageY - deltaY > 0) || moveOut) {
tpX = e.pageX - deltaX;
tpY = e.pageY - deltaY;
} else if (e.pageX - deltaX <= 0 && e.pageY - deltaY > 0) {
tpX = 0;
tpY = e.pageY - deltaY;
} else if (e.pageX - deltaX > 0 && e.pageY - deltaY <= 0) {
tpX = e.pageX - deltaX;
tpY = 0;
}
obj.css({
"left": (tpX),
"top": (tpY)
});
return false;
} function stop() {
$(document).unbind({
'mousemove': move,
'mouseup': stop
});
}
} /**
* 提示
* @param {Object} msg
* @param {Object} t
* @param {Object} style 自定义样式,必须是json格式
*/
function tip(msg, t, style) {
var tipId = 'tip' + (new Date().getTime());
var styleto = '';
if (!isNull(style)) {
for (var s in style) {
styleto += s + ': ' + style[s] + ';';
}
}
$('body').append("<div id='" + tipId + "' class='tip' style='" + styleto + "'>" + msg + "</div>");
setTimeout(function() {
$('#' + tipId).addClass('tipKill');
setTimeout(function() {
$('#' + tipId).remove();
}, t);
}, t);
} /**
* 空判断
* @param {Object} obj
*/
function isNull(obj) {
return obj == null || obj == undefined || obj == '' || obj == NaN || ('' + obj) == '{}';
}

5.效果图

基于作者 “三宝鸭” 代码重构,实现了高度动态化

理了一下逻辑和注释,增强了兼容性,大家仍可以 diy 成更适合自己的模块

参考链接:原生 JS 写拖拽文件上传_三宝鸭的博客-CSDN博客

转载请附上本文链接

最新文章

  1. Node-Webkit打包
  2. 再谈 $* 和 $@ 在 Bash 中的表现
  3. JS根据登录的城市不同调用不同的内容
  4. [SoapUI] 同一个Resource不同参数时,在两个step里默认打开总是同一个Resource
  5. MSSql得到表的结构和字段
  6. 练习2 J题 - 多项式求和
  7. NET应用——使用RSA构建相对安全的数据交互
  8. Flask技术问题汇总
  9. codeforces1003D(贪心)
  10. Spring IOC(四)FactoryBean
  11. python 信号量,Event, 定时器
  12. [基础架构]PeopleSoft Tuxedo 重要文件说明
  13. HDU 4280 Island Transport(网络流,最大流)
  14. Hadoop家族学习路线图v
  15. 如何使用 SSH 连接 VMWare 虚拟机中的 Ubuntu
  16. 【agc023E】Inversions(线段树,动态规划)
  17. 九度OJ 1183 守形数 (模拟)
  18. django 关闭debug模式,报500错误
  19. 0908期 HTML form表单
  20. 五、Springboot 之 自定义配置文件及读取配置文件

热门文章

  1. CentOS 8.2 对k8s基础环境配置
  2. 2022-08-11-emo了
  3. 如何用Virtualbox搭建一个虚拟机
  4. 齐博x1前台后台地址跳转的处理
  5. CJK备注
  6. 深度优先搜索(Depth-First-Search)dfs代码模板
  7. 关系抽取--Relation Extraction: Perspective from Convolutional Neural Networks
  8. Redis的攻击手法
  9. 09 | 从容器到容器云:谈谈Kubernetes的本质
  10. Kubernetes介绍和资源管理