element前端實現(xiàn)壓縮圖片的功能
前言
隨著現(xiàn)在手機像素,拍照功能越來越好,隨之而來的是本地圖片越來越大,那么如何更好的將本地圖片上傳到后端接口呢?這是后臺管理系統(tǒng)常見的場景和頭疼的問題,這里分享下個人的方法。
實現(xiàn)效果
如下圖所示,從 580kb -> 壓縮后 150kb
實現(xiàn)步驟
1、父級引入封裝文件
//頁面上 <el-dialog title="壓縮圖片" :visible.sync="compressImgVisible" width="700" foot-hide > <uploadImg /> </el-dialog> //js中 data() { return { compressImgVisible: false, }
2、首先實現(xiàn)上傳功能,使用el-upload,
封裝uploadImg.vue
<template> <div class="uploadImgBody"> <!--上傳圖片部分--> <el-upload class="upload-image" ref="upload" :action="action" :headers="headers" :multiple="multiple" :data="data" :name="name" :show-file-list="showFileList" :drag="drag" :accept="accept" :list-type="listType" :auto-upload="autoUpload" :disabled="is_disabled" :before-upload="beforeUpload" > <!--彈框展示上傳以后的圖片--> <img class="fileImg" v-if="mrImgUrl" :src="mrImgUrl" > <div v-else> <i class="el-icon-plus"></i> </div> </el-upload> </div> </template> <script> //element的上傳圖片,壓縮圖片組件 export default { props:{ /** * 自動上傳參數(shù) * */ autoUpload:{ // 是否需要選取完自動上傳功能 type: Boolean, default: true }, // 默認圖片,父級傳過來 http開頭的文件 mrImgUrl:{ type: String, default: '' }, action:{//上傳的地址 type: String, default: '' }, headers: {//設(shè)置上傳的請求頭部 type:Object, default: () => { return {} } }, data: {//上傳時額外帶的參數(shù) type:Object, default: () => { return {} } }, name:{//上傳的文件字段名 type: String, default: 'file' }, cookieOK:{//支持發(fā)送 cookie 憑證信息 type: Boolean, default: true }, /** * 公共參數(shù) * */ showFileList:{//是否顯示已上傳文件列表 type: Boolean, default: false }, drag:{//是否啟用拖拽上傳 type: Boolean, default: false }, accept:{//接受文件類型-圖片上傳類型-不同的格式之間以逗號隔開 type: String, default: '.jpg,.jpeg,.png' }, listType:{ // 文件列表的類型 - text/picture/picture-card type: String, default: 'picture-card' }, fileList:{//已上傳的文件列表, type:Array, default: () => { return [ { name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100' } ] } }, is_disabled:{//是否禁止,true是禁止,false不禁止 type: Boolean, default: false }, multiple:{//是否可以多選 type: Boolean, default: true }, }, watch: {}, data() { return { } }, methods: { /** * @上傳文件之前的鉤子 * @params file 圖片的file文件 * @return uploadFile 把文件發(fā)送給父級 * @tip 多選會調(diào)用多次該方法 */ beforeUpload(file) { this.$emit('uploadFile',file); return } }, } </script> <style lang='scss' scoped> .uploadImgBody{ height: auto; .upload-image{ width:200px; height: 200px; .fileImg{ width:100%; height: 100%; } } .showImg{ width:100px; height: 100px; } } </style>
3、加入壓縮功能
邏輯:
首先,把file文件轉(zhuǎn)成 canvas圖片,然后canvas壓縮圖片利用canvas.toDataURL()將canvas繪制的圖像轉(zhuǎn)成圖片從而達到壓縮圖片尺寸的效果
具體方法:其中 dataUrl 就是拿到的canvas圖片的base64地址
/** * @壓縮公共方法 * @params file * @return 壓縮后的文件,支持兩種,file和 blob */ compressImg(file) { const reader = new FileReader(); // readAsDataURL 方法會讀取指定的 Blob 或 File 對象。讀取操作完成的時候,readyState 會變成已完成DONE,并觸發(fā) loadend (en-US) 事件, // 同時 result 屬性將包含一個data:URL格式的字符串(base64編碼)以表示所讀取文件的內(nèi)容。 reader.readAsDataURL(file); reader.onload = () => { const img = new Image(); img.src = reader.result; img.onload = () => { // 圖片的寬高 const w = img.width; const h = img.height; const canvas = document.createElement("canvas"); // canvas對圖片進行裁剪,這里設(shè)置為圖片的原始尺寸 canvas.width = w; canvas.height = h; const ctx = canvas.getContext("2d"); // canvas中,png轉(zhuǎn)jpg會變黑底,所以先給canvas鋪一張白底 ctx.fillStyle = "#fff"; // fillRect()方法繪制一個填充了內(nèi)容的矩形,這個矩形的開始點(左上點)在 // (x, y) ,它的寬度和高度分別由width 和 height 確定,填充樣式由當(dāng)前的fillStyle 決定。 ctx.fillRect(0, 0, canvas.width, canvas.height); // 繪制圖像 ctx.drawImage(img, 0, 0, w, h); // canvas轉(zhuǎn)圖片達到圖片壓縮效果 // 返回一個包含圖片展示的 data URI base64 在指定圖片格式為 image/jpeg 或 image/webp的情況下, // 可以從 0 到 1 的區(qū)間內(nèi)選擇圖片的質(zhì)量。如果超出取值范圍,將會使用默認值 0.92。其他參數(shù)會被忽略。 const dataUrl = canvas.toDataURL("image/jpeg", 0.8); this.dialogImageUrl = dataUrl }; }; },
4、拿到的base64地址,不能直接給后端,要轉(zhuǎn)格式,這里提供兩種,一是file文件,跟壓縮前的格式一樣,還有一種是blob方法
// canvas生成的格式為base64,需要進行轉(zhuǎn)化, base64->file dataURLtoFile(dataurl,fileName) { let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], fileName, {type:mime}) }, // canvas生成的格式為base64,需要進行轉(zhuǎn)化, base64->blob dataURLtoBlob(dataurl) { const arr = dataurl.split(","), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); },
實現(xiàn)源碼(上傳+壓縮):
uploadImg.vue
<template> <div class="uploadImgBody"> <!--上傳圖片部分--> <el-upload class="upload-image" ref="upload" :action="action" :headers="headers" :multiple="multiple" :data="data" :name="name" :show-file-list="showFileList" :drag="drag" :accept="accept" :list-type="listType" :auto-upload="autoUpload" :disabled="is_disabled" :before-upload="beforeUpload" > <!--彈框展示上傳以后的圖片--> <img class="fileImg" v-if="mrImgUrl" :src="mrImgUrl" > <div v-else> <i class="el-icon-plus"></i> </div> </el-upload> 源圖片大?。?lt;span v-if="sourceFile.size">{{ sourceFile.size/1024 }}</span> kb <el-button @click="compressImgFun" style="display: block;margin:10px 0;">點我壓縮</el-button> 壓縮圖片大小:<span v-if="compressFile.size">{{compressFile.size/1024 }}</span> kb <img v-if="dialogImageUrl" class="showImg" :src="dialogImageUrl" > </div> </template> <script> //element的上傳圖片,壓縮圖片組件 export default { props:{ /** * 自動上傳參數(shù) * */ autoUpload:{ // 是否需要選取完自動上傳功能 type: Boolean, default: true }, // 默認圖片,父級傳過來 http開頭的文件 mrImgUrl:{ type: String, default: '' }, action:{//上傳的地址 type: String, default: '' }, headers: {//設(shè)置上傳的請求頭部 type:Object, default: () => { return {} } }, data: {//上傳時額外帶的參數(shù) type:Object, default: () => { return {} } }, name:{//上傳的文件字段名 type: String, default: 'file' }, cookieOK:{//支持發(fā)送 cookie 憑證信息 type: Boolean, default: true }, /** * 公共參數(shù) * */ showFileList:{//是否顯示已上傳文件列表 type: Boolean, default: false }, drag:{//是否啟用拖拽上傳 type: Boolean, default: false }, accept:{//接受文件類型-圖片上傳類型-不同的格式之間以逗號隔開 type: String, default: '.jpg,.jpeg,.png' }, listType:{ // 文件列表的類型 - text/picture/picture-card type: String, default: 'picture-card' }, fileList:{//已上傳的文件列表, type:Array, default: () => { return [ { name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100' } ] } }, is_disabled:{//是否禁止,true是禁止,false不禁止 type: Boolean, default: false }, multiple:{//是否可以多選 type: Boolean, default: true }, }, watch: {}, data() { return { dialogImageUrl:'',//源圖片 sourceFile:{}, //上傳后的圖片 compressFile:{} //壓縮后的圖片 } }, methods: { /** * @上傳文件之前的鉤子 * @params file 圖片的file文件 * @return uploadFile 把文件發(fā)送給父級 * @tip 多選會調(diào)用多次該方法 */ beforeUpload(file) { this.sourceFile = file this.$emit('uploadFile',file); return }, compressImgFun(){ this.compressImg(this.sourceFile) console.log('壓縮前的圖片文件:file'); console.log(this.sourceFile); }, /** * @壓縮公共方法 * @params file * @return 壓縮后的文件,支持兩種,file和 blob */ compressImg(file) { const reader = new FileReader(); // readAsDataURL 方法會讀取指定的 Blob 或 File 對象。讀取操作完成的時候,readyState 會變成已完成DONE,并觸發(fā) loadend (en-US) 事件, // 同時 result 屬性將包含一個data:URL格式的字符串(base64編碼)以表示所讀取文件的內(nèi)容。 reader.readAsDataURL(file); reader.onload = () => { const img = new Image(); img.src = reader.result; img.onload = () => { // 圖片的寬高 const w = img.width; const h = img.height; const canvas = document.createElement("canvas"); // canvas對圖片進行裁剪,這里設(shè)置為圖片的原始尺寸 canvas.width = w; canvas.height = h; const ctx = canvas.getContext("2d"); // canvas中,png轉(zhuǎn)jpg會變黑底,所以先給canvas鋪一張白底 ctx.fillStyle = "#fff"; // fillRect()方法繪制一個填充了內(nèi)容的矩形,這個矩形的開始點(左上點)在 // (x, y) ,它的寬度和高度分別由width 和 height 確定,填充樣式由當(dāng)前的fillStyle 決定。 ctx.fillRect(0, 0, canvas.width, canvas.height); // 繪制圖像 ctx.drawImage(img, 0, 0, w, h); // canvas轉(zhuǎn)圖片達到圖片壓縮效果 // 返回一個包含圖片展示的 data URI base64 在指定圖片格式為 image/jpeg 或 image/webp的情況下, // 可以從 0 到 1 的區(qū)間內(nèi)選擇圖片的質(zhì)量。如果超出取值范圍,將會使用默認值 0.92。其他參數(shù)會被忽略。 const dataUrl = canvas.toDataURL("image/jpeg", 0.8); this.dialogImageUrl = dataUrl // base64格式文件轉(zhuǎn)成Blob文件格式 let blobFile = this.dataURLtoBlob(dataUrl); console.log("壓縮后的圖片:Blob文件----------"); console.log(blobFile); // base64格式文件轉(zhuǎn)成file文件格式 let fileName = this.sourceFile.name let fileImg = this.dataURLtoFile(dataUrl,fileName); console.log("壓縮后的圖片:file文件----------"); console.log(fileImg); this.compressFile = fileImg }; }; }, // canvas生成的格式為base64,需要進行轉(zhuǎn)化, base64->file dataURLtoFile(dataurl,fileName) { let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], fileName, {type:mime}) }, // canvas生成的格式為base64,需要進行轉(zhuǎn)化, base64->blob dataURLtoBlob(dataurl) { const arr = dataurl.split(","), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); }, }, } </script> <style lang='scss' scoped> .uploadImgBody{ height: auto; .upload-image{ width:200px; height: 200px; .fileImg{ width:100%; height: 100%; } } .showImg{ width:100px; height: 100px; } } </style>
更多資料:
前端圖片壓縮(幾乎無損)_藍格子.的博客-CSDN博客_前端無損壓縮
到此這篇關(guān)于element前端實現(xiàn)壓縮圖片的功能的文章就介紹到這了,更多相關(guān)element 壓縮圖片內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用vue+element?ui實現(xiàn)走馬燈切換預(yù)覽表格數(shù)據(jù)
這次做項目的時候遇到需要切換預(yù)覽表格數(shù)據(jù)的需求,所以下面這篇文章主要給大家介紹了關(guān)于使用vue+element?ui實現(xiàn)走馬燈切換預(yù)覽表格數(shù)據(jù)的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-08-08Vue2.0實現(xiàn)調(diào)用攝像頭進行拍照功能 exif.js實現(xiàn)圖片上傳功能
這篇文章主要為大家詳細介紹了Vue2.0實現(xiàn)調(diào)用攝像頭進行拍照功能,以及圖片上傳功能引用exif.js,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-04-04vue中的路由跳轉(zhuǎn)tabBar圖片和文字的高亮效果
這篇文章主要介紹了vue中的路由跳轉(zhuǎn)tabBar圖片和文字的高亮效果,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10vue自定義底部導(dǎo)航欄Tabbar的實現(xiàn)代碼
這篇文章主要介紹了vue自定義底部導(dǎo)航欄Tabbar的實現(xiàn)代碼,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-09-09