Jq /Js 拖动选择文件

 必须先引入 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博客

 

转载请附上本文链接

posted @ 2022-03-17 17:26  散人长情  阅读(355)  评论(0编辑  收藏  举报