const imgUtil = new (require('./imgUtil'))()
// 默认配置
const defaultConfig = {
restrictiveSize: 0.5 * 1024 * 1024, // 0.5MB
fixed: 1024,
quality: 0.3,
isOriginSize: false
}
// 是否支持
const isCanUseCompressImage = wx.canIUse('compressImage')
// 压缩耗时
let compressTime = Date.now()
let canvas = null
/**
* 压缩图片
* 支持类型:JPG
* @param {string} canvasId canvas的id
* @param {string} canvasWidthName 控制canvas宽度的变量名
* @param {string} canvasHeightName 控制canvas高度的变量名
*
*/
function ImgCompress(canvasId, canvasWidthName, canvasHeightName) {
// 如果canvas上下文未创建,则创建canvas上下文
canvas = canvas || wx.createCanvasContext(canvasId)
// 压缩完成后销毁canvas
const destroyCanvas = function (newWidth, newHeight, fixed, that) {
canvas.clearRect(0, 0, newWidth, newHeight)
canvas = null
const width = fixed || defaultConfig.fixed
return that.setData({
[canvasWidthName]: width,
[canvasHeightName]: width * 9 / 16,
})
}
/**
* 压缩图片
* @param {string} filePath 图片的路径/临时路径
* @param {object} that 页面的this对象
* @param {int} quality 压缩质量(0-1,值越小压缩得越厉害)
* @param {bool} isOriginSize 是否保持原有宽高
* @param {int} fixed 修正宽度(最小宽度)
* @param {int} restrictiveSize 图片限制大小,单位:B
* @param {int} orderNumber 顺序序号
* @returns { Promise } errMsg: ok-成功 fail-失败, filePath: 压缩后路径, originPath: 原始路径, orderNumber: 序号
*/
this.compressImage = async function (filePath, that, quality, isOriginSize, fixed, restrictiveSize, orderNumber) {
var limitSize = restrictiveSize || defaultConfig.restrictiveSize
const res = await imgUtil.getImgSize(filePath, orderNumber)
console.log('当前序号:', res.orderNumber);
console.log('原始大小(单位KB):', res.size * 1.0 / 1024)
// 超过限制则进行压缩
if (res.size > limitSize) {
const info = await imgUtil.getImgInfo(res.originalPath)
return new Promise((resolve, reject) => {
var cttSuccess = function (cres) {
compressTime = Date.now() - compressTime
console.log('压缩时长:', compressTime * 1.0 / 1000)
return resolve({
errMsg: 'ok',
filePath: cres.tempFilePath,
originPath: res.originalPath,
orderNumber: res.orderNumber
})
}
var cttFail = function (err) {
console.log('canvasToTempFilePath失败,图片路径:', res.originalPath)
console.log('canvasToTempFilePath失败:', err)
return resolve({
errMsg: 'fail',
filePath: '',
originPath: '',
orderNumber: res.orderNumber
})
}
// 如果支持原生压缩api并且图片的大小小于3MB则使用原生压缩
// 图片的大小在小于3MB时原生压缩api性能较好,耗时较少
if (isCanUseCompressImage && res.size <= 3 * 1024 * 1024) {
console.log('调用了CompressImage')
wx.compressImage({
src: info.path,
quality: (quality || defaultConfig.quality) * 100,
success: cttSuccess,
fail: cttFail
})
} else {
var newInfo = {
newW = info.width,
newH = info.height
}
// 不保持原有宽高,采用等比例缩放后的宽高
if(!isOriginSize){
newInfo = imgUtil.getUniformScaleInfo(info.width, info.height, quality || defaultConfig.quality, fixed || defaultConfig.fixed)
}
console.log('图片大小', {
original: { oriW: info.width, oriH: info.height },
newInfo: { newW: newInfo.newW, newH: newInfo.newH }
})
// 设置canvas的宽和高
that.setData({
[canvasWidthName]: newInfo.newW,
[canvasHeightName]: newInfo.newH
}, function () {
setTimeout(function () {
canvas.drawImage(info.path, 0, 0, newInfo.newW, newInfo.newH)
canvas.draw(false, function () {
// 保持原有宽高通过设置质量进行压缩,不保持原有宽高质量为1
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: newInfo.newW,
height: newInfo.newH,
destWidth: newInfo.newW,
destHeight: newInfo.newH,
canvasId: canvasId,
fileType: 'jpg',
quality: isOriginSize ? quality || defaultConfig.quality : 1,
success: cttSuccess,
fail: function (err) {
// 失败后进行一次重试
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: newInfo.newW,
height: newInfo.newH,
destWidth: newInfo.newW,
destHeight: newInfo.newH,
canvasId: canvasId,
fileType: 'jpg',
quality: isOriginSize ? quality || defaultConfig.quality : 1,
success: cttSuccess,
fail: cttFail,
complete: function () {
destroyCanvas(newInfo.newW, newInfo.newH, fixed, that)
}
})
},
complete: function () {
destroyCanvas(newInfo.newW, newInfo.newH, fixed, that)
}
})
})
}, 30)
})
}
})
} else {
return {
errMsg: 'ok',
filePath: res.originalPath,
originPath: res.originalPath,
orderNumber: res.orderNumber
}
}
}
/**
* 删除压缩过程中保存的图片
* @param {string} tempFilePath 保存的图片的路径
*/
this.removeSavedFile = function (tempFilePath) {
wx.removeSavedFile({
filePath: tempFilePath,
success: function () {
console.log('删除保存的图片\n\r')
},
fail: function (err) {
console.log('删除保存的图片失败:' + err.errMsg + '\n\r')
}
})
}
}
// 组合使用构造函数模式与原型模式
ImgCompress.prototype = {
constructor: ImgCompress
}
module.exports = ImgCompress