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绘制的图像转成图片从而达到压缩图片尺寸的效果
具体方法:其中 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" 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:{ /** * 自动上传参数 * */ 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>
更多资料:
前端图片压缩(几乎无损)_蓝格子.的博客-CSDN博客_前端无损压缩
到此这篇关于element前端实现压缩图片的功能的文章就介绍到这了,更多相关element 压缩图片内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!