这篇文章主要讲解了“element前端如何实现压缩图片功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“element前端如何实现压缩图片功能”吧!
如下图所示,从 580kb -> 压缩后 150kb
1、父级引入封装文件
//页面上 <el-dialog title="压缩图片" :visible.sync="compressImgVisible" width="700" foot-hide > <uploadImg /> </el-dialog> //js中 data() { return { compressImgVisible: false, }
2、首先实现上传功能,使用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:{ /** * 自动上传参数 * */ autoUpload:{ // 是否需要选取完自动上传功能 type: Boolean, default: true }, // 默认图片,父级传过来 http开头的文件 mrImgUrl:{ type: String, default: '' }, action:{//上传的地址 type: String, default: '' }, headers: {//设置上传的请求头部 type:Object, default: () => { return {} } }, data: {//上传时额外带的参数 type:Object, default: () => { return {} } }, name:{//上传的文件字段名 type: String, default: 'file' }, cookieOK:{//支持发送 cookie 凭证信息 type: Boolean, default: true }, /** * 公共参数 * */ 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 把文件发送给父级 * @tip 多选会调用多次该方法 */ 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文件转成 canvas图片,然后canvas压缩图片利用canvas.toDataURL()将canvas绘制的图像转成图片从而达到压缩图片尺寸的效果
HTMLCanvasElement.toDataURL()
具体方法:其中 dataUrl 就是拿到的canvas图片的base64地址
/** * @压缩公共方法 * @params file * @return 压缩后的文件,支持两种,file和 blob */ compressImg(file) { const reader = new FileReader(); // readAsDataURL 方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成DONE,并触发 loadend (en-US) 事件, // 同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。 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对图片进行裁剪,这里设置为图片的原始尺寸 canvas.width = w; canvas.height = h; const ctx = canvas.getContext("2d"); // canvas中,png转jpg会变黑底,所以先给canvas铺一张白底 ctx.fillStyle = "#fff"; // fillRect()方法绘制一个填充了内容的矩形,这个矩形的开始点(左上点)在 // (x, y) ,它的宽度和高度分别由width 和 height 确定,填充样式由当前的fillStyle 决定。 ctx.fillRect(0, 0, canvas.width, canvas.height); // 绘制图像 ctx.drawImage(img, 0, 0, w, h); // canvas转图片达到图片压缩效果 // 返回一个包含图片展示的 data URI base64 在指定图片格式为 image/jpeg 或 image/webp的情况下, // 可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92。其他参数会被忽略。 const dataUrl = canvas.toDataURL("image/jpeg", 0.8); this.dialogImageUrl = dataUrl }; }; },
4、拿到的base64地址,不能直接给后端,要转格式,这里提供两种,一是file文件,跟压缩前的格式一样,还有一种是blob方法
// canvas生成的格式为base64,需要进行转化, 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,需要进行转化, 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 }); },
实现源码(上传+压缩):
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> 源图片大小:<span v-if="sourceFile.size">{{ sourceFile.size/1024 }}</span> kb <el-button @click="compressImgFun" >点我压缩</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:{ /** * 自动上传参数 * */ autoUpload:{ // 是否需要选取完自动上传功能 type: Boolean, default: true }, // 默认图片,父级传过来 http开头的文件 mrImgUrl:{ type: String, default: '' }, action:{//上传的地址 type: String, default: '' }, headers: {//设置上传的请求头部 type:Object, default: () => { return {} } }, data: {//上传时额外带的参数 type:Object, default: () => { return {} } }, name:{//上传的文件字段名 type: String, default: 'file' }, cookieOK:{//支持发送 cookie 凭证信息 type: Boolean, default: true }, /** * 公共参数 * */ 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 把文件发送给父级 * @tip 多选会调用多次该方法 */ 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,并触发 loadend (en-US) 事件, // 同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。 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对图片进行裁剪,这里设置为图片的原始尺寸 canvas.width = w; canvas.height = h; const ctx = canvas.getContext("2d"); // canvas中,png转jpg会变黑底,所以先给canvas铺一张白底 ctx.fillStyle = "#fff"; // fillRect()方法绘制一个填充了内容的矩形,这个矩形的开始点(左上点)在 // (x, y) ,它的宽度和高度分别由width 和 height 确定,填充样式由当前的fillStyle 决定。 ctx.fillRect(0, 0, canvas.width, canvas.height); // 绘制图像 ctx.drawImage(img, 0, 0, w, h); // canvas转图片达到图片压缩效果 // 返回一个包含图片展示的 data URI base64 在指定图片格式为 image/jpeg 或 image/webp的情况下, // 可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92。其他参数会被忽略。 const dataUrl = canvas.toDataURL("image/jpeg", 0.8); this.dialogImageUrl = dataUrl // base64格式文件转成Blob文件格式 let blobFile = this.dataURLtoBlob(dataUrl); console.log("压缩后的图片:Blob文件----------"); console.log(blobFile); // base64格式文件转成file文件格式 let fileName = this.sourceFile.name let fileImg = this.dataURLtoFile(dataUrl,fileName); console.log("压缩后的图片:file文件----------"); console.log(fileImg); this.compressFile = fileImg }; }; }, // canvas生成的格式为base64,需要进行转化, 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,需要进行转化, 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>
感谢各位的阅读,以上就是“element前端如何实现压缩图片功能”的内容了,经过本文的学习后,相信大家对element前端如何实现压缩图片功能这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。