js 實(shí)現(xiàn)文件上傳樣式詳情
1、概述
這個(gè)js包括按鈕樣式,列表樣式、帶有刪除、添加、放大(使用的是自帶的放大功能,提供有API來(lái)放入你的彈窗來(lái)進(jìn)行展示)
可監(jiān)聽的事件 | Value | wdaasd |
---|---|---|
onlargeClickCallBack | 如果想使用自己的彈窗,只需要監(jiān)聽這個(gè)函數(shù),拿到返回值給你的彈窗的img->href進(jìn)行賦值即可 | imgFile對(duì)象(包括這個(gè)被點(diǎn)擊圖片的全部信息)that(這個(gè)js的全局唯一對(duì)象,可以在這里面拿到你所有的值) |
ondialogBeforeClose | 自帶的彈窗被關(guān)閉的回調(diào) | object 返回值是一個(gè)對(duì)象 對(duì)象.event -> 被執(zhí)行的事件的源事件 對(duì)象.imgFile -> 被點(diǎn)擊關(guān)閉彈窗時(shí),目前彈窗上展示的圖片對(duì)象信息 |
onaddImgList | 每添加一個(gè)圖片的回調(diào) | file -> 文件對(duì)象 that -> (這個(gè)js的全局唯一對(duì)象,可以在這里面拿到你所有的值) |
2、創(chuàng)建對(duì)象的參數(shù)
參數(shù) | 含義 |
---|---|
maxFileLength | 最大可以存在的文件個(gè)數(shù) 默認(rèn)值:2 |
maxFileSize | 每個(gè)文件單獨(dú)最大的文件大小 默認(rèn)值:1024 (1M) |
fileSuffix | 允許上傳的文件后綴 默認(rèn)值:['mp4', 'mp3', 'word', 'pdf', 'ppt', 'excel', 'jpg', 'png'] |
StopDialog | 是否阻止打開自帶的默認(rèn)彈窗 默認(rèn)值:false |
shadeDialogStyle | 如果打開自帶彈窗的選項(xiàng),那么這個(gè)控制打開的彈窗高寬多少默認(rèn)值:[null, null],默認(rèn)為null為自適應(yīng),如果想要設(shè)置百分比和px 請(qǐng)直接改變數(shù)組[0,1],數(shù)組第一項(xiàng)代表寬,第二項(xiàng)代表高 |
showBtnImgStyle | 是否開啟按鈕樣式 默認(rèn)值: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> <!-- 在不開啟按鈕樣式時(shí),這個(gè)外層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、監(jiān)聽例子
//如果不想使用自帶的彈窗,可以選擇監(jiān)聽file對(duì)象的onlargeClickCallBack函數(shù) file.callBack.onlargeClickCallBack = function (img, that) {} file.callBack.ondialogBeforeClose = function (event) {} file.callBack.onaddImgList = function () {}
4、使用方法
項(xiàng)目目錄如上圖所示
如果要使用,只需要把js
放入你的項(xiàng)目路徑下,然后把img
放到你的static
目錄(靜態(tài)資源路徑)。
這里js里面默認(rèn)引入的圖標(biāo)是 ./ 的相對(duì)路徑,請(qǐng)自行搜索然后進(jìn)行更改為你項(xiàng)目的文件路徑
上圖項(xiàng)目示例為可直接打開查看的完整包,后文有下載地址
5、源代碼
此源代碼為不包括圖標(biāo)的源代碼,全部在一個(gè)html頁(yè)面里面
<!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構(gòu)造函數(shù) function File(obj) { // 文件總個(gè)數(shù) this.fileLength = 0; // 文件數(shù)組 this.fileList = []; // 對(duì)象參數(shù)配置文件 this.config = { // 最大文件個(gè)數(shù) maxFileLength: obj.maxFileLength || 2, // 最大文件大小 maxFileSize: obj.maxFileSize || 1024, // 允許的文件后綴 fileSuffix: obj.fileSuffix || ['mp4', 'mp3', 'word', 'pdf', 'ppt', 'excel', 'jpg', 'png'], // 是否阻止默認(rèn)打開彈窗 StopDialog: obj.StopDialog || false, // 彈窗的樣式 寬 高 shadeDialogStyle: obj.shade || [null, null], // 是否開啟按鈕樣式 showBtnImgStyle: obj.showBtn || false, }; // fileDom中存儲(chǔ)的唯一的dom節(jié)點(diǎn) this.dom = { // input 文件選中輸入框dom inputDom: null, // append-item 添加點(diǎn)擊dom imageItemDom: null, // 要向hj-append-item節(jié)點(diǎn)后面追加圖片的dom appendItemDom: null, // 要向hj-file-list節(jié)點(diǎn)后面添加圖片列表的dom appendListDom: null, }; // 事件處理對(duì)象 this.event = { // append-item點(diǎn)擊事件處理 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); }) // 防止在按鈕模式下,會(huì)出現(xiàn)第一次沒(méi)有加載完成,高長(zhǎng)為0的不正常情況 img.onload = () => { div.appendChild(div2); document.body.appendChild(div); this.privateUtils.computeDialogWH(img, div2); } }, }, this.method = { // 過(guò)濾圖片 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節(jié)點(diǎn)中 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; } } // 創(chuàng)建刪除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); }, } // 暴露的監(jiān)聽Api this.callBack = { // 阻止默認(rèn)自帶的打開彈窗 onlargeClickCallBack: (img, that) => {}, // 自帶的彈窗被關(guān)閉時(shí)的回調(diào) // {event: 點(diǎn)擊的源事件對(duì)象 imgFile: 被關(guān)閉的那張圖片的全局file對(duì)象信息} ondialogBeforeClose: (object) => {}, // 每一次添加圖片列表時(shí)的回調(diào) 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"; } }, // 計(jì)算彈窗的高度和長(zhǎng)度 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); // 如果不想使用自帶的彈窗,可以選擇監(jiān)聽file對(duì)象的onlargeClickCallBack函數(shù) file.callBack.onlargeClickCallBack = function (img, that) {} file.callBack.ondialogBeforeClose = function (event) {} file.callBack.onaddImgList = function () {} // 加載初始信息,比如dom節(jié)點(diǎn)的添加 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("沒(méi)有找到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>
到此這篇關(guān)于js 實(shí)現(xiàn)文件上傳樣式詳情的文章就介紹到這了,更多相關(guān)js 實(shí)現(xiàn)文件上傳樣式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS前端面試數(shù)組扁平化手寫flat函數(shù)示例
這篇文章主要為大家介紹了JS前端面試數(shù)組扁平化手寫flat函數(shù)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07微信小程序之滾動(dòng)視圖容器的實(shí)現(xiàn)方法
這篇文章主要介紹了微信小程序之滾動(dòng)視圖容器的實(shí)現(xiàn)方法的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09微信小程序 本地?cái)?shù)據(jù)存儲(chǔ)實(shí)例詳解
這篇文章主要介紹了微信小程序 本地?cái)?shù)據(jù)存儲(chǔ)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04直觀詳細(xì)的typescript隱式類型轉(zhuǎn)換圖文詳解
這篇文章主要為大家介紹了直觀詳細(xì)的typescript隱式類型轉(zhuǎn)換圖文詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07微信小程序 scroll-view組件實(shí)現(xiàn)列表頁(yè)實(shí)例代碼
這篇文章主要介紹了微信小程序 scroll-view組件實(shí)現(xiàn)列表頁(yè)實(shí)例代碼的相關(guān)資料,scroll-view組件介紹scroll-view是微信小程序提供的可滾動(dòng)視圖組件,其主要作用是可以用來(lái)做手機(jī)端經(jīng)常會(huì)看到的上拉加載 ,需要的朋友可以參考下2016-12-12微信小程序 天氣預(yù)報(bào)開發(fā)實(shí)例代碼源碼
這篇文章主要介紹了微信小程序 天氣預(yù)報(bào)開發(fā)實(shí)例代碼源碼的相關(guān)資料,這里含有源碼,需要的朋友可以參考下2017-01-01微信小程序 頁(yè)面滑動(dòng)事件的實(shí)例詳解
這篇文章主要介紹了微信小程序 頁(yè)面滑動(dòng)事件的實(shí)例詳解的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10在微信小程序中渲染HTML內(nèi)容3種解決方案及分析與問(wèn)題解決
在開發(fā)微信小程序時(shí)我們會(huì)在小程序內(nèi)加入純HTML代碼,且HTML中包括圖片,視頻,甚至是事件,微信小程序?yàn)槲覀兲峁┝?種解決方法,但它們的功能與實(shí)現(xiàn)方式與最終效果并不理想2020-01-01詳解JavaScript中數(shù)組的相關(guān)知識(shí)
這篇文章主要介紹了JavaScript中中數(shù)組的相關(guān)知識(shí),是JS入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-07-07