|
@@ -1,201 +1,94 @@
|
|
|
-//通过canvas将图片压缩至指定大小
|
|
|
+import methods from "@/common/methodTool";
|
|
|
+let num = 1;
|
|
|
+let _resolve;
|
|
|
+let _reject;
|
|
|
|
|
|
-//判断图片大小是否满足需求,limitSize的单位是kb
|
|
|
-function imageSizeIsLessLimitSize(
|
|
|
- imagePath,
|
|
|
- limitSize,
|
|
|
- lessCallback,
|
|
|
- moreCallback
|
|
|
-) {
|
|
|
- //获取文件信息
|
|
|
- wx.getFileSystemManager().getFileInfo({
|
|
|
- filePath: imagePath,
|
|
|
- success: (res) => {
|
|
|
- console.log("压缩前图片大小", res, res.size / 1024, "kb");
|
|
|
- if (res.size > limitSize) {
|
|
|
- moreCallback();
|
|
|
- } else {
|
|
|
- lessCallback();
|
|
|
- }
|
|
|
- },
|
|
|
- });
|
|
|
+function getBase64Size(base64) {
|
|
|
+ if (base64) {
|
|
|
+ base64 = base64.split(",")[1].split("=")[0];
|
|
|
+ var strLength = base64.length;
|
|
|
+ var fileLength = strLength - (strLength / 8) * 2;
|
|
|
+ return Math.floor(fileLength); // 向下取整
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
-//将图片画在画布上并获取画好之后的图片的路径
|
|
|
-function getCanvasImage(canvasId, imagePath, imageW, imageH, getImgSuccess) {
|
|
|
- //创建画布内容
|
|
|
- const ctx = wx.createCanvasContext(canvasId);
|
|
|
- //图片画上去,imageW和imageH是画上去的尺寸,图像和画布间隔都是0
|
|
|
- ctx.drawImage(imagePath, 0, 0, imageW, imageH);
|
|
|
- //这里一定要加定时器,给足够的时间去画(所以每次递归最少要耗时200ms,多次递归很耗时!)
|
|
|
- ctx.draw(
|
|
|
- false,
|
|
|
- setTimeout(() => {
|
|
|
- //把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径
|
|
|
- wx.canvasToTempFilePath({
|
|
|
- canvasId: canvasId,
|
|
|
- x: 0,
|
|
|
- y: 0,
|
|
|
- width: imageW,
|
|
|
- height: imageH,
|
|
|
- quality: 1, // 取0-1,1最高质量
|
|
|
- fileType: "jpg",
|
|
|
- success: (res) => {
|
|
|
- console.log(res, 989898);
|
|
|
- //将取出的图片路径通过回调函数返回
|
|
|
- getImgSuccess(res.tempFilePath);
|
|
|
- },
|
|
|
- });
|
|
|
- }, 200)
|
|
|
- );
|
|
|
+//获得图片大小
|
|
|
+function imageSizeIsLessLimitSize(imagePath, limitSize) {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ wx.getFileSystemManager().getFileInfo({
|
|
|
+ filePath: imagePath,
|
|
|
+ success: (res) => {
|
|
|
+ resolve(res.size);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
//主函数,默认限制大小2048kb即2mb,drawWidth是绘画区域的大小
|
|
|
//初始值传入为画布自身的边长(我们这是一个正方形的画布)
|
|
|
-function getLessLimitSizeImage(
|
|
|
- canvasId,
|
|
|
- imagePath,
|
|
|
- limitSize = 1024,
|
|
|
- drawWidth,
|
|
|
- callback
|
|
|
-) {
|
|
|
- //判断图片尺寸是否满足要求
|
|
|
- imageSizeIsLessLimitSize(
|
|
|
- imagePath,
|
|
|
- limitSize,
|
|
|
- (lessRes) => {
|
|
|
- //满足要求走callback,将压缩后的文件路径返回
|
|
|
- console.log("满足要求走callback:", imagePath);
|
|
|
- callback(imagePath);
|
|
|
- },
|
|
|
- (moreRes) => {
|
|
|
- //不满足要求需要压缩的时候
|
|
|
- wx.getImageInfo({
|
|
|
- src: imagePath,
|
|
|
- success: (imageInfo) => {
|
|
|
- let maxSide = Math.max(imageInfo.width, imageInfo.height);
|
|
|
- let windowW = drawWidth;
|
|
|
- let scale = 1;
|
|
|
- /*
|
|
|
- 这里的目的是当绘画区域缩小的比图片自身尺寸还要小的时候
|
|
|
- 取图片长宽的最大值,然后和当前绘画区域计算出需要放缩的比例
|
|
|
- 然后再画经过放缩后的尺寸,保证画出的一定是一个完整的图片。由于每次递归绘画区域都会缩小,
|
|
|
- 所以不用担心scale永远都是1绘画尺寸永远不变的情况,只要不满足压缩后体积的要求
|
|
|
- 就会缩小绘画区域,早晚会有绘画区域小于图片尺寸的情况发生
|
|
|
- */
|
|
|
- if (maxSide > windowW) {
|
|
|
- scale = windowW / maxSide;
|
|
|
- }
|
|
|
- //trunc是去掉小数
|
|
|
- let imageW = Math.trunc(imageInfo.width * scale);
|
|
|
- let imageH = Math.trunc(imageInfo.height * scale);
|
|
|
- // console.log('调用压缩',imageW,imageH);
|
|
|
- //图片在规定绘画区域上画并获取新的图片的path
|
|
|
- getCanvasImage(
|
|
|
- canvasId,
|
|
|
- imagePath,
|
|
|
- imageW,
|
|
|
- imageH,
|
|
|
- (pressImgPath) => {
|
|
|
- /*
|
|
|
- 再去检查是否满足要求,始终缩小绘画区域,让图片适配绘画区域
|
|
|
- 这里乘以0.95是必须的,如果不缩小绘画区域,会出现尺寸比绘画区域小,
|
|
|
- 而体积比要求压缩体积大的情况出现,就会无穷递归下去,因为scale的值永远是1
|
|
|
- 但0.95不是固定的,你可以根据需要自己改,0到1之间,越小则绘画区域缩小的越快
|
|
|
- 但不建议取得太小,绘画区域缩小的太快,压出来的将总是很糊的
|
|
|
- */
|
|
|
- getLessLimitSizeImage(
|
|
|
- canvasId,
|
|
|
- pressImgPath,
|
|
|
- limitSize,
|
|
|
- drawWidth * 0.95,
|
|
|
- callback
|
|
|
- );
|
|
|
- }
|
|
|
- );
|
|
|
- },
|
|
|
- });
|
|
|
- }
|
|
|
- );
|
|
|
-}
|
|
|
-function compressWx(url, quality, cb) {
|
|
|
- //不满足要求需要压缩的时候
|
|
|
- wx.getImageInfo({
|
|
|
- src: url,
|
|
|
- success: (imageInfo) => {
|
|
|
- let maxSide = Math.max(imageInfo.width, imageInfo.height);
|
|
|
- let windowW = drawWidth;
|
|
|
- let scale = 1;
|
|
|
- if (maxSide > windowW) {
|
|
|
- scale = windowW / maxSide;
|
|
|
- }
|
|
|
- //trunc是去掉小数
|
|
|
- let imageW = Math.trunc(imageInfo.width * scale);
|
|
|
- let imageH = Math.trunc(imageInfo.height * scale);
|
|
|
- //创建画布内容
|
|
|
- const ctx = wx.createCanvasContext(canvasId);
|
|
|
- //图片画上去,imageW和imageH是画上去的尺寸,图像和画布间隔都是0
|
|
|
- ctx.drawImage(imagePath, 0, 0, imageW, imageH);
|
|
|
- //这里一定要加定时器,给足够的时间去画(所以每次递归最少要耗时200ms,多次递归很耗时!)
|
|
|
- ctx.draw(
|
|
|
- false,
|
|
|
- setTimeout(() => {
|
|
|
- //把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径
|
|
|
- wx.canvasToTempFilePath({
|
|
|
- canvasId: canvasId,
|
|
|
- x: 0,
|
|
|
- y: 0,
|
|
|
- width: imageW,
|
|
|
- height: imageH,
|
|
|
- quality: quality, // 取0-1,1最高质量
|
|
|
- fileType: "jpg",
|
|
|
- success: (res) => {
|
|
|
- cb(res.tempFilePath);
|
|
|
- },
|
|
|
- });
|
|
|
- }, 200)
|
|
|
- );
|
|
|
+function getLessLimitSizeImage(imagePath, quality) {
|
|
|
+ uni.compressImage({
|
|
|
+ src: imagePath,
|
|
|
+ quality,
|
|
|
+ success: (res) => {
|
|
|
+ console.log(res.tempFilePath, res, "压缩后");
|
|
|
+ _resolve(res.tempFilePath);
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
-function compressH5(url, quality, cb) {
|
|
|
+function compressH5(url, quality) {
|
|
|
let image = new Image();
|
|
|
image.onload = function () {
|
|
|
- var h = this.height * (quality / 1); // 默认按比例压缩
|
|
|
- var w = this.width * (quality / 1);
|
|
|
var canvas = document.createElement("canvas");
|
|
|
+ canvas.width = image.width;
|
|
|
+ canvas.height = image.height;
|
|
|
var ctx = canvas.getContext("2d");
|
|
|
- var anw = document.createAttribute("width");
|
|
|
- anw.nodeValue = w;
|
|
|
- var anh = document.createAttribute("height");
|
|
|
- anh.nodeValue = h;
|
|
|
- canvas.setAttributeNode(anw);
|
|
|
- canvas.setAttributeNode(anh);
|
|
|
- ctx.drawImage(image, 0, 0, w, h); //压缩比例
|
|
|
+ ctx.drawImage(image, 0, 0, this.height, this.width); //压缩比例
|
|
|
var base64 = canvas.toDataURL("image/jpeg", quality);
|
|
|
- cb(base64);
|
|
|
+ _resolve(base64);
|
|
|
};
|
|
|
image.src = url;
|
|
|
image.setAttribute("crossOrigin", "Anonymous");
|
|
|
image.onerror = () => {
|
|
|
- reject(new Error("urlToBase64 error"));
|
|
|
+ _reject(new Error("zip error"));
|
|
|
};
|
|
|
}
|
|
|
-function myCompressImage(url, limitSize = 2048, cb) {
|
|
|
- limitSize = limitSize * 1024;
|
|
|
- const size = url.size;
|
|
|
- if (size < limitSize) {
|
|
|
- return cb(url);
|
|
|
- }
|
|
|
- const quality = limitSize / size;
|
|
|
- // #ifdef MP-WEIXIN
|
|
|
- let canvasId = "zipCanvas";
|
|
|
- let drawWidth = wx.getSystemInfoSync().windowWidth;
|
|
|
- getLessLimitSizeImage(canvasId, url.path, limitSize, drawWidth, cb);
|
|
|
- // #endif
|
|
|
- // #ifdef H5
|
|
|
- compressH5(url.path, quality, cb);
|
|
|
- // #endif
|
|
|
+function myCompressImage(url, limitSize = 2048) {
|
|
|
+ return new Promise(async (resolve, reject) => {
|
|
|
+ _resolve = resolve;
|
|
|
+ _reject = resolve;
|
|
|
+ limitSize = limitSize * 1024;
|
|
|
+ // 获得size
|
|
|
+ if (typeof url == "string") {
|
|
|
+ // base64
|
|
|
+ if (methods.isBase64(url)) {
|
|
|
+ url = {
|
|
|
+ path: url,
|
|
|
+ size: getBase64Size(url),
|
|
|
+ };
|
|
|
+ }
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
+ url = {
|
|
|
+ path: url,
|
|
|
+ size: await imageSizeIsLessLimitSize(url),
|
|
|
+ };
|
|
|
+ // #endif
|
|
|
+ }
|
|
|
+ const size = url.size;
|
|
|
+ console.log(size, "压缩前");
|
|
|
+ if (size < limitSize) {
|
|
|
+ return _resolve(url);
|
|
|
+ }
|
|
|
+ num++;
|
|
|
+ const quality = limitSize / size;
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
+ getLessLimitSizeImage(url.path, quality);
|
|
|
+ // #endif
|
|
|
+ // #ifdef H5
|
|
|
+ compressH5(url.path, quality);
|
|
|
+ // #endif
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
export default myCompressImage;
|