最近在开发中有需求需要压缩图片,这里我就记录下压缩方法以及遇到的坑。
首先需要用到canvas,这里我是写成一个组件,在需要用到的地方引入就好。
由于这里跨文件了,所以这里用vuex将this记录下来。
<template>
<canvas canvas-id="compression-image" style="position: fixed; left: -99999px; top: -99999px; width: 1000px; height: 1000px;" />
</template>
<script>
export default {
name: "compression-image",
mounted() {
this.$store.commit("setCompressionImageThis", this);
},
beforeDestroy() {
this.$store.commit("setCompressionImageThis", null);
},
}
</script>
vuex中的代码如下:
/** 存放compressionImage组件的一些数据 */
export default {
state: {
// compressionImage组件的this
compressionImageThis: null,
},
getters: {
/** 获取compressionImage组件的实例 */
getCompressionImageThis: state => {
return state.compressionImageThis;
}
},
mutations: {
/** 设置compressionImage组件的实例 */
setCompressionImageThis: (state, data) => {
state.compressionImageThis = data;
}
}
}
引入之后,页面上就有canvas了,之后就在js代码部分进行图片压缩,如下:
// 这边引入vuex对象 - 获取到之前存的this
import store from "@/store/index.js";
/**
* 处理对图片进行压缩
* 配合compression-image组件一起使用,在需要用到的页面引入compression-image组件就能对图片进行压缩
* @param {string} url 图片路径
* @param {number} size 文件大小
* @param {string} fileType 文件类型
* */
export const getCompressionImage = (url, size = 0, fileType = 'jpg') => {
return new Promise(async resolve => {
// 获取this对象
const _this = store.getters.getCompressionImageThis;
// 判断this是否存在
if(!_this) {
resolve(url);
}
// 默认判断的size
const defaultSize = 1024 * 1024;
// 画布的尺寸
const canvasWidth = 1000;
const canvasHeight = 1000;
// 获取canvas上下文对象
const context = uni.createCanvasContext("compression-image", _this);
// 清空画布 - 这边的 清空尺寸 来自于compression-image组件画布的大小
context.clearRect(0, 0, canvasWidth, canvasHeight);
// 图片缩放的比例
let ratio = 1;
// 判断是否需要缩放
if(size > defaultSize) {
ratio = Math.sqrt(size / defaultSize);
}
// 获取图片的信息
uni.getImageInfo({
src: url,
success: res => {
let { path, width, height } = res;
width = width / ratio;
height = height / ratio;
// 判断缩放后的是否超出画布
if(width > canvasWidth || height > canvasHeight) {
if(width > height) {
ratio = width / canvasWidth;
}
else {
ratio = height / canvasHeight;
}
width = width / ratio;
height = height / ratio;
}
// 将图片绘制到canvas中
context.drawImage(path, 0, 0, width, height);
// 进行绘制...
context.draw(false, () => {
// 保存图片为临时路径
uni.canvasToTempFilePath({
canvasId: "compression-image",
x: 0,
y: 0,
width: width,
height: height,
destWidth: width,
destHeight: height,
fileType,
success: res => {
resolve(res.tempFilePath);
},
fail: err => {
resolve(url);
}
}, _this);
});
},
fail: () => {
resolve(url);
},
});
});
}
最后使用😃
// HTML部分使用组件
<compression-image />
<script>
// JS部分 - 这里随便举例子
const test = async () {
const url = await getCompressionImage("这里传入需要压缩图片的路径", "这里传入图片大小", "这里传入图片的类型");
console.log(url, "这里就是压缩后的图片路径,传给后端就好啦!");
}
</script>
遇到的问题:
真机调试的时候绘制图片是白屏 ----- 解决办法就是调整canvas画布的宽高,canvas画布不能太大。