Jq /Js 拖动选择文件
2024-09-08 06:06:07
必须先引入 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博客
转载请附上本文链接
最新文章
- Node-Webkit打包
- 再谈 $* 和 $@ 在 Bash 中的表现
- JS根据登录的城市不同调用不同的内容
- [SoapUI] 同一个Resource不同参数时,在两个step里默认打开总是同一个Resource
- MSSql得到表的结构和字段
- 练习2 J题 - 多项式求和
- NET应用——使用RSA构建相对安全的数据交互
- Flask技术问题汇总
- codeforces1003D(贪心)
- Spring IOC(四)FactoryBean
- python 信号量,Event, 定时器
- [基础架构]PeopleSoft Tuxedo 重要文件说明
- HDU 4280 Island Transport(网络流,最大流)
- Hadoop家族学习路线图v
- 如何使用 SSH 连接 VMWare 虚拟机中的 Ubuntu
- 【agc023E】Inversions(线段树,动态规划)
- 九度OJ 1183 守形数 (模拟)
- django 关闭debug模式,报500错误
- 0908期 HTML form表单
- 五、Springboot 之 自定义配置文件及读取配置文件