js 实现文件上传样式详情
程序员文章站
2022-03-04 23:19:46
目录1、概述这个js包括按钮样式,列表样式、带有删除、添加、放大(使用的是自带的放大功能,提供有api来放入你的弹窗来进行展示) 可监听的事件...
1、概述
这个js包括按钮样式,列表样式、带有删除、添加、放大(使用的是自带的放大功能,提供有api来放入你的弹窗来进行展示)
可监听的事件 | value | wdaasd |
---|---|---|
onlargeclickcallback | 如果想使用自己的弹窗,只需要监听这个函数,拿到返回值给你的弹窗的img->href进行赋值即可 | imgfile对象(包括这个被点击图片的全部信息)that(这个js的全局唯一对象,可以在这里面拿到你所有的值) |
ondialogbeforeclose | 自带的弹窗被关闭的回调 | object 返回值是一个对象 对象.event -> 被执行的事件的源事件 对象.imgfile -> 被点击关闭弹窗时,目前弹窗上展示的图片对象信息 |
onaddimglist | 每添加一个图片的回调 | file -> 文件对象 that -> (这个js的全局唯一对象,可以在这里面拿到你所有的值) |
2、创建对象的参数
参数 | 含义 |
---|---|
maxfilelength | 最大可以存在的文件个数 默认值:2 |
maxfilesize | 每个文件单独最大的文件大小 默认值:1024 (1m) |
filesuffix | 允许上传的文件后缀 默认值:['mp4', 'mp3', 'word', 'pdf', 'ppt', 'excel', 'jpg', 'png'] |
stopdialog | 是否阻止打开自带的默认弹窗 默认值:false |
shadedialogstyle | 如果打开自带弹窗的选项,那么这个控制打开的弹窗高宽多少默认值:[null, null],默认为null为自适应,如果想要设置百分比和px 请直接改变数组[0,1],数组第一项代表宽,第二项代表高 |
showbtnimgstyle | 是否开启按钮样式 默认值:false |
使用代码示例:
<div class="hj-file"> <input type="file" file="" class="hj-file-input"> <div class="hj-box hj-append-item"> <div class="append-item margin-class"> <div class="img-push"> <img src="./img/push.png" alt=""> </div> </div> </div> <!-- 在不开启按钮样式时,这个外层div可以删除 --> <div class="hj-btn-box hj-hidden"> <div class="hj-btn"> 选择图片 </div> </div> <!-- 文件信息列表 --> <div class="hj-file-list"> </div> </div> var file = new file({ maxfilelength: 2, maxfilesize: 1024, filesuffix: ['mp4', 'mp3', 'word', 'pdf', 'ppt', 'excel', 'png', 'jpg'], stopdialog: false, showbtn: false }); inithjfile(file);
3、监听例子
//如果不想使用自带的弹窗,可以选择监听file对象的onlargeclickcallback函数 file.callback.onlargeclickcallback = function (img, that) {} file.callback.ondialogbeforeclose = function (event) {} file.callback.onaddimglist = function () {}
4、使用方法
项目目录如上图所示
如果要使用,只需要把js
放入你的项目路径下,然后把img
放到你的static
目录(静态资源路径)。
这里js里面默认引入的图标是 ./ 的相对路径,请自行搜索然后进行更改为你项目的文件路径
上图项目示例为可直接打开查看的完整包,后文有下载地址
5、源代码
此源代码为不包括图标的源代码,全部在一个html页面里面
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>document</title> </head> <style> * { padding: 0; margin: 0; } body { width: 100vw; height: 100vh; /* display: flex; justify-content: center; align-items: center; */ } /* .box { width: 600px; } */ .hj-file { width: 100%; /* height: 100%; */ } .hj-file-input { display: none; } .hj-box { display: flex; flex-wrap: wrap; } .append-item { width: 150px; height: 150px; border: 1px dashed #b1b5bb; border-radius: 5px; background-color: #fbfdff; display: flex; align-items: center; margin: 10px; justify-content: center; } .image-item { width: 150px; height: 150px; border-radius: 5px; margin: 10px; display: flex; justify-content: center; align-items: center; border: 1px solid #eaedf1; position: relative; background-size: 100% 100%; background-repeat: no-repeat; transition: 1s; animation: translaters 1s; } .image-item-delete { animation: bottom-translaters .7s; } @keyframes translaters { 0% { opacity: .2; transform: translate(0, -50%); } 100% { opacity: 1; transform: translate(0); } } @keyframes bottom-translaters { 0% { opacity: 1; transform: translate(0, 0); } 100% { opacity: .2; transform: translate(0, 50%); } } .img-push img { width: 60px; height: 60px; } .append-item:hover { border-color: #00d2fc; } .margin-class { margin-bottom: 20px; } .first { background-image: url('./img/66.jpg'); } .z-index-promote { z-index: 3; } .largeimg img { cursor: pointer; width: 30px; height: 30px; transition: .6s; display: none; } .deleteimg img { cursor: pointer; width: 40px; height: 40px; display: none; } .image-item:hover::before { content: ""; z-index: 2; background-color: #42393999; width: 100%; position: absolute; height: 100%; border-radius: 5px; transition: .6s; animation: transparency linear .6s; } .image-item:hover .largeimg img { display: block; animation: transparency linear .6s; } .image-item:hover .deleteimg img { display: block; animation: transparency linear .6s; } @keyframes transparency { 0% { opacity: 0; } 100% { opacity: 1; } } .hj-shade { width: 100vw; height: 100vh; background-color: #302d2d99; position: fixed; overflow: hidden; z-index: 1978; display: flex; left: 50%; top: 50%; transform: translate(-50%, -50%); justify-content: center; align-items: center; animation: hj-shade-sacle .5s; } @keyframes hj-shade-sacle { 0% { transform: translate(-50%, -50%) scale(0%); } 100% { transform: translate(-50%, -50%) scale(100%); } } @keyframes hj-shade-hidden { 0% { transform: translate(-50%, -50%) scale(100%); } 100% { transform: translate(-50%, -50%) scale(0%); } } .hj-shade-hidden { animation: hj-shade-hidden .5s; } .hj-shade { overflow: auto; } .hj-shade .hj-box { width: 60%; height: 80%; padding: 20px 10px 10px 10px; background-size: 100% 100%; background-color: white; } .hj-shade .hj-box .hj-img { width: 100%; overflow: auto; height: 100%; } .hj-file-list .hj-file-list-item { background-color: white; color: #8cacb3; display: flex; line-height: 2; font-size: 0.8em; } .hj-file-list .hj-file-list-item:hover { background-color: #00d2fc70; color: white; } .hj-file-list .hj-file-list-item .hj-left { width: 30%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .hj-file-list .hj-file-list-item .hj-left span { margin-left: 20px; cursor: pointer; } .hj-file-list .hj-file-list-item .hj-right { width: 30%; display: flex; align-items: center; justify-content: end; } .hj-file-list .hj-file-list-item .hj-right span { margin-right: 20px; } .hj-file-list .hj-file-list-item .hj-right img { width: 20px; height: 20px; cursor: pointer; } @keyframes hj-list-hidden { 0% { opacity: 1; } 100% { opacity: 0; } } .hj-list-hidden { animation: hj-list-hidden .7s; } .hj-btn-box { margin-bottom: 25px; } .hj-btn-box .hj-btn { margin-left: 20px; cursor: pointer; background-color: #009efa; width: 30%; line-height: 2; border-radius: 4px; color: white; font-size: 1.2em; text-align: center; } .hj-hidden { display: none; } </style> <body> <div class="box"> <div class="hj-file"> <input type="file" file="" class="hj-file-input"> <div class="hj-box hj-append-item"> <div class="append-item margin-class"> <div class="img-push"> <img src="./img/push.png" alt=""> </div> </div> </div> <div class="hj-btn-box hj-hidden"> <div class="hj-btn"> 选择图片 </div> </div> <div class="hj-file-list"> </div> </div> </div> <script> // file构造函数 function file(obj) { // 文件总个数 this.filelength = 0; // 文件数组 this.filelist = []; // 对象参数配置文件 this.config = { // 最大文件个数 maxfilelength: obj.maxfilelength || 2, // 最大文件大小 maxfilesize: obj.maxfilesize || 1024, // 允许的文件后缀 filesuffix: obj.filesuffix || ['mp4', 'mp3', 'word', 'pdf', 'ppt', 'excel', 'jpg', 'png'], // 是否阻止默认打开弹窗 stopdialog: obj.stopdialog || false, // 弹窗的样式 宽 高 shadedialogstyle: obj.shade || [null, null], // 是否开启按钮样式 showbtnimgstyle: obj.showbtn || false, }; // filedom中存储的唯一的dom节点 this.dom = { // input 文件选中输入框dom inputdom: null, // append-item 添加点击dom imageitemdom: null, // 要向hj-append-item节点后面追加图片的dom appenditemdom: null, // 要向hj-file-list节点后面添加图片列表的dom appendlistdom: null, }; // 事件处理对象 this.event = { // append-item点击事件处理 imageitemclick: () => { this.dom.inputdom.click(); }, // input 文件选中输入框选择完图片之后事件处理 changeloadfile: (file) => { this.method.filterfile(file.target.files); }, // 图片删除事件 imgdeleteclick: (id) => { for (let index = 0; index < this.filelist.length; index++) { if (this.filelist[index].id == id) { let _before = this.filelist.slice(0, index == this.filelist.length ? index - 1 : index); let _after = this.filelist.slice(index + 1); _before = _before.concat(_after); // 删除图片 this.method.deleteimg(id); settimeout(() => { this.filelist[index].dom.remove(); this.filelist[index].listdom.remove(); this.filelength--; this.filelist = _before; }, 600); break; } } 1 }, // 图片放大事件 imglargeclick: (id) => { let imgfile = this.privateutils.foreachfilelisttoid(id); console.log(imgfile); this.callback.onlargeclickcallback(imgfile, this); if (this.config.stopdialog) return; let hjshadediv = document.getelementsbyclassname('hj-shade'); if (hjshadediv.length != 0) return; let div = document.createelement('div'); div.classname = 'hj-shade'; let div2 = document.createelement('div'); div2.classname = 'hj-box'; let img = document.createelement('img'); img.classname = 'hj-img'; img.src = imgfile.base64; div2.appendchild(img); div.addeventlistener('click', (event) => { this.callback.ondialogbeforeclose({ event: event, imgfile: imgfile, }); div.classname = div.classname + ' hj-shade-hidden'; settimeout(() => { document.body.removechild(div); }, 500); }) // 防止在按钮模式下,会出现第一次没有加载完成,高长为0的不正常情况 img.onload = () => { div.appendchild(div2); document.body.appendchild(div); this.privateutils.computedialogwh(img, div2); } }, }, this.method = { // 过滤图片 filterfile: (list) => { for (let index = 0; index < list.length; index++) { let size = parseint(list[index].size / 1024); let suffix = list[index].name.substring(list[index].name .lastindexof('.') + 1); // 是否符合后缀 let istrue = false; // 判断文件大小 if (size > this.config.maxfilesize) { console.log("文件太大"); break; } for (let j = 0; j < this.config.filesuffix.length; j++) { if (suffix == this.config.filesuffix[j]) { istrue = true; break; } } if (istrue) { let id = parseint(math.random() * 100000); this.filelist.push({ id: id, file: list[index], base64: '', dom: '', listdom: '', }); console.log(this.filelist); this.method.streamtoimgbase64(list[index], id); } else { console.log("文件后缀不符合"); } } }, // 处理图片展示 streamtoimgbase64: (file, id) => { var filereader = new filereader(); filereader.onload = (data) => { this.method.appendimage(data.target.result, id); } filereader.readasdataurl(file); }, // 追加图片到dom节点中 appendimage: (url, id) => { let div = document.createelement('div'); div.classname = 'image-item margin-class'; div.style.backgroundimage = 'url(' + url + ')'; for (let index = 0; index < this.filelist.length; index++) { if (this.filelist[index].id == id) { this.filelist[index].dom = div; this.filelist[index].base64 = url; break; } } // 创建删除dom,全部使用addeventlistener let largedom = document.createelement('div'); largedom.classname = 'largeimg z-index-promote'; largedom.innerhtml = `<img src="./img/big.png" alt="">`; largedom.addeventlistener('click', () => { this.event.imglargeclick(id); }) let deletedom = document.createelement('div'); deletedom.classname = 'deleteimg z-index-promote'; deletedom.innerhtml = `<img src="./img/delete.png" alt="">`; deletedom.addeventlistener('click', () => { this.event.imgdeleteclick(id); }) div.appendchild(largedom); div.appendchild(deletedom); this.dom.appenditemdom.appendchild(div); this.filelength++; // 添加图片列表 this.method.addimglist(id); }, // 删除图片 deleteimg: (id) => { for (let index = 0; index < this.filelist.length; index++) { if (this.filelist[index].id == id) { let item = this.filelist[index]; let cless = item.dom.getattribute('class'); let clesslist = item.listdom.getattribute('class'); this.filelist[index].dom.setattribute("class", cless + " image-item-delete"); this.filelist[index].listdom.setattribute("class", clesslist + " hj-list-hidden ") break; } } }, // 添加图片列表 addimglist: (id) => { let file = this.privateutils.foreachfilelisttoid(id); this.callback.onaddimglist(file, this); let div = document.createelement('div'); div.classname = ' hj-file-list-item ' let div$left = document.createelement('div'); let div$right = document.createelement('div'); let file$img = document.createelement('img'); let filesize = this.privateutils.computefilesize(file.file.size); file$img.src = './img/delete-balck.png'; div$left.classname = ' hj-left '; div$right.classname = ' hj-right '; div$left.innerhtml = `<span>${file.file.name}</span>` div$right.innerhtml = `<span>${filesize}</span>`; div$left.addeventlistener('click', () => { this.event.imglargeclick(id); }) file$img.addeventlistener('click', () => { this.event.imgdeleteclick(id); }) div$right.appendchild(file$img); div.appendchild(div$left); div.appendchild(div$right); for (let index = 0; index < this.filelist.length; index++) { if (id == this.filelist[index].id) { this.filelist[index].listdom = div; break; } } this.dom.appendlistdom.appendchild(div); }, } // 暴露的监听api this.callback = { // 阻止默认自带的打开弹窗 onlargeclickcallback: (img, that) => {}, // 自带的弹窗被关闭时的回调 // {event: 点击的源事件对象 imgfile: 被关闭的那张图片的全局file对象信息} ondialogbeforeclose: (object) => {}, // 每一次添加图片列表时的回调 onaddimglist: (file, that) => {}, }, this.privateutils = { foreachfilelisttoid: (id) => { for (let index = 0; index < this.filelist.length; index++) { if (id == this.filelist[index].id) { return this.filelist[index]; } } }, computefilesize: (size) => { let result = parseint(size / 1024); if (result < 1024) { return result + '.kb'; } else if (result >= 1024) { return parseint(result / 1024) + ".mb"; } }, // 计算弹窗的高度和长度 computedialogwh: (img, dom) => { let w = this.config.shadedialogstyle[0]; let h = this.config.shadedialogstyle[1]; let w2 = img.naturalwidth; let h2 = img.naturalheight; if (w2 > window.innerwidth * 0.9) { w2 = window.innerwidth * 0.7; h2 = window.innerheight * 0.7; } dom.style.width = w == null ? w2 + "px" : w; dom.style.height = h == null ? h2 + "px" : h; } } } var file = new file({ maxfilelength: 2, maxfilesize: 1024, filesuffix: ['mp4', 'mp3', 'word', 'pdf', 'ppt', 'excel', 'png', 'jpg'], stopdialog: false, showbtn: false }); inithjfile(file); // 如果不想使用自带的弹窗,可以选择监听file对象的onlargeclickcallback函数 file.callback.onlargeclickcallback = function (img, that) {} file.callback.ondialogbeforeclose = function (event) {} file.callback.onaddimglist = function () {} // 加载初始信息,比如dom节点的添加 function inithjfile(file) { console.log(file); let input_dom = document.getelementsbyclassname('hj-file-input')[0]; let imageitem_dom = document.getelementsbyclassname('append-item')[0]; let appenditem_dom = document.getelementsbyclassname('hj-append-item')[0]; let appendlist_dom = document.getelementsbyclassname('hj-file-list')[0]; file.dom.inputdom = input_dom; file.dom.imageitemdom = imageitem_dom; file.dom.appendlistdom = appendlist_dom; if (file.config.showbtnimgstyle) { // 开启按钮模式 appenditem_dom.style.display = 'none'; let btn = document.getelementsbyclassname('hj-btn-box'); console.log(btn); if (btn.length != 0) { btn[0].classname = 'hj-btn-box'; btn[0].children[0].addeventlistener('click', file.event.imageitemclick); } else { console.log("没有找到btn class"); throw new error('未定义按钮模式所需的html') } } file.dom.appenditemdom = appenditem_dom; file.dom.imageitemdom.addeventlistener('click', file.event.imageitemclick); file.dom.inputdom.addeventlistener('change', file.event.changeloadfile) } </script> </body> </html>
到此这篇关于js 实现文件上传样式详情的文章就介绍到这了,更多相关js 实现文件上传样式内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
上一篇: 阿里规范:为何boolean类型变量命名禁用is开头
下一篇: 张郃的待遇为何比张辽好很多?