一、压缩静态图片
/*** 压缩图片方法* @param {file} file 文件* @param {Number} quality 图片质量(取值 0-1 之间默认 0.52)*/
export function compressImg(file, quality) {let qualitys = 0.52if (parseInt((file.size / 1024).toFixed(2)) < 1024) {qualitys = 0.85}if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {qualitys = 0.92}if (quality) {qualitys = quality}if (file[0]) {return Promise.all(Array.from(file).map(e => this.compressImg(e, qualitys))) // 如果是 file 数组返回 Promise 数组} else {return new Promise((resolve) => {if ((file.size / 1024).toFixed(2) < 300) {resolve({file: file})} else {const reader = new FileReader() // 创建 FileReaderreader.readAsDataURL(file)reader.onload = ({target: {result: src}}) => {const image = new Image() // 创建 img 元素image.onload = async () => {const canvas = document.createElement('canvas') // 创建 canvas 元素const context = canvas.getContext('2d')const originWidth = image.widthconst originHeight = image.heightlet targetWidth = image.widthlet targetHeight = image.heightif (1 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 10 * 1024) {var maxWidth = 1600var maxHeight = 1600targetWidth = originWidthtargetHeight = originHeight// 图片尺寸超过的限制if (originWidth > maxWidth || originHeight > maxHeight) {if (originWidth / originHeight > maxWidth / maxHeight) {// 更宽,按照宽度限定尺寸targetWidth = maxWidthtargetHeight = Math.round(maxWidth * (originHeight / originWidth))} else {targetHeight = maxHeighttargetWidth = Math.round(maxHeight * (originWidth / originHeight))}}}if (10 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 20 * 1024) {maxWidth = 1400maxHeight = 1400targetWidth = originWidthtargetHeight = originHeight// 图片尺寸超过的限制if (originWidth > maxWidth || originHeight > maxHeight) {if (originWidth / originHeight > maxWidth / maxHeight) {// 更宽,按照宽度限定尺寸targetWidth = maxWidthtargetHeight = Math.round(maxWidth * (originHeight / originWidth))} else {targetHeight = maxHeighttargetWidth = Math.round(maxHeight * (originWidth / originHeight))}}}canvas.width = targetWidthcanvas.height = targetHeightcontext.clearRect(0, 0, targetWidth, targetHeight)context.drawImage(image, 0, 0, targetWidth, targetHeight) // 绘制 canvasconsole.log('typetypetypetype',file.type);const canvasURL = canvas.toDataURL(file.type, qualitys)const buffer = atob(canvasURL.split(',')[1])let length = buffer.lengthconst bufferArray = new Uint8Array(new ArrayBuffer(length))while (length--) {bufferArray[length] = buffer.charCodeAt(length)}const miniFile = new File([bufferArray], file.name, {type: file.type})resolve({origin: file,file: miniFile,beforeSrc: src,afterSrc: canvasURL,beforeKB: Number((file.size / 1024).toFixed(2)),afterKB: Number((miniFile.size / 1024).toFixed(2)),qualitys: qualitys})}image.src = src}}})}
}
使用方式:
import { compressImg } from '@/utils/index'// 第一个参数是file对象,第二个参数是压缩倍数,不传默认0.52
compressImg(file.raw)
二、gif动态图片压缩
参考网址:GitCode - 全球开发者的开源社区,开源代码托管平台
1.下载 npm i gifsicle-wasm-browser --save 包
npm i gifsicle-wasm-browser --save
2.在需要的页面或组件引入
import gifsicle from "gifsicle-wasm-browser";
3.使用方式
// 可以使用 async await 模式,也可以使用.then
gifsicle.run({input: [{file: file.raw, name: 'input.gif',}],command: [`-O2 --lossy=160 input.gif -o /out/out.gif`],
}).then(outGifFiles => {console.log(outGifFiles);// [File,File,File ...]
});
博主压缩案例:可能是因为插件的原因,4mb以上进行压缩时间比较合适,小于4mb就不建议压缩了
//原图大小: 3320733 3.16MB
-O1 --lossy=20 1.gif -o /out/out.gif 压缩:19028574 20秒
-O1 --lossy=160 1.gif -o /out/out.gif 压缩:14047276 20秒
-O2 --lossy=40 1.gif -o /out/out.gif 压缩:3285702 34秒
-O2 --lossy=160 1.gif -o /out/out.gif 压缩:2957546 30秒
-O3 --lossy=160 1.gif -o /out/out.gif 压缩:2940185 83秒//原图大小: 4883735 4.65MB
-O1 --lossy=20 1.gif -o /out/out.gif 压缩:4353783 6秒
-O1 --lossy=160 1.gif -o /out/out.gif 压缩:2324117 5秒
-O2 --lossy=40 1.gif -o /out/out.gif 压缩:3463351 9秒
-O2 --lossy=160 1.gif -o /out/out.gif 压缩:2479152 8秒
-O3 --lossy=160 1.gif -o /out/out.gif 压缩:2479108 20秒//原图大小: 15482425 14.76MB
-O1 --lossy=20 1.gif -o /out/out.gif 压缩:15162166 11秒
-O1 --lossy=160 1.gif -o /out/out.gif 压缩:7987047 9秒
-O2 --lossy=40 1.gif -o /out/out.gif 压缩:10409003 20秒
-O2 --lossy=160 1.gif -o /out/out.gif 压缩:7233579 15秒
-O3 --lossy=160 1.gif -o /out/out.gif 压缩:7164005 45秒
const limit10M = file.size /1024/1024 < 10;
if(!limit10M) {return this.$message.warning('上传文件不能超过10M!');
}let newfile;
if( file.raw.type !=='image/gif'){// 图片压缩let res = await compressImg(file.raw)newfile = res.file
}else{// gif压缩 4MB以下不需要压缩const limit4M = file.size /1024/1024 < 4;if(!limit4M) {let res = await gifsicle.run({input: [{file: file.raw, name: 'input.gif',}],command: [`-O1 --lossy=20 input.gif -o /out/out.gif`],})console.log('resres',res);newfile = res[0]}else{newfile = file.raw}
}// 使用 newfile 里面的值传入给后端
压缩案例对比图:查看下图