- A+
所属分类:Web前端
- 这个js包括按钮样式,列表样式、带有删除、添加、放大(使用的是自带的放大功能,提供有API来放入你的弹窗来进行展示)
可监听的事件 | Value | wdaasd |
---|---|---|
onlargeClickCallBack | 如果想使用自己的弹窗,只需要监听这个函数,拿到返回值给你的弹窗的img->href进行赋值即可 | imgFile对象(包括这个被点击图片的全部信息)that(这个js的全局唯一对象,可以在这里面拿到你所有的值) |
ondialogBeforeClose | 自带的弹窗被关闭的回调 | object 返回值是一个对象 对象.event -> 被执行的事件的源事件 对象.imgFile -> 被点击关闭弹窗时,目前弹窗上展示的图片对象信息 |
onaddImgList | 每添加一个图片的回调 | file -> 文件对象 that -> (这个js的全局唯一对象,可以在这里面拿到你所有的值) |
创建对象的参数
参数 | 含义 |
---|---|
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="js 实现文件上传样式" 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);
监听例子
//如果不想使用自带的弹窗,可以选择监听file对象的onlargeClickCallBack函数 file.callBack.onlargeClickCallBack = function (img, that) {} file.callBack.ondialogBeforeClose = function (event) {} file.callBack.onaddImgList = function () {}
如何使用
项目目录如上图所示
如果要使用,只需要把js放入你的项目路径下,然后把img放到你的static目录(静态资源路径)。
这里js里面默认引入的图标是 ./ 的相对路径,请自行搜索然后进行更改为你项目的文件路径
上图项目示例为可直接打开查看的完整包,后文有下载地址
源代码
此源代码为不包括图标的源代码,全部在一个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="js 实现文件上传样式" 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="js 实现文件上传样式" 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="js 实现文件上传样式" 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>
链接:https://pan.baidu.com/s/1Te8Umgl24b0g7-wyCnydUw
提取码:6666