在微信小程序的开发过程中,为了防止用户在上传图片时出现过大文件的情况,造成后台的加载负担,我们通常会在前台加上大小的限制或在上传时就对图片进行压缩
微信小程序官方为我们提供了一个API:wx.compressImage,
但仔细查看后我们发现,这个API在iOS端仅支持压缩JPG格式的图片,显然不太符合我们的需求。
经过一番查阅后,决定采用canvas绘图的方式来对图片重新进行绘制,从而达到压缩的效果。
下面是具体的实现流程:
<canvas id="myCanvas" class="canvas-case" type="2d" style="border: 1px solid; width: 300px; height: 150px;" />
首先,创建一份画布,如果不需要图片的显示的话可以直接移出可视范围
const query = this.createSelectorQuery()
let dom = query.select('#myCanvas') // 获取 canvas 元素
核心代码:
async contraction(file, canvasId, config = {
maxWidth: 1024,
maxHeight: 768
}) {
try {
let ctxInfo = await new Promise((resolve, reject) => {
// 获取图片原始宽高
let width = file.width
let height = file.height
// 计算图片当前大小和目标大小的比例:目标大小 / 图片当前大小
// 根据比例调整图片的尺寸:
// 新宽度 = 原始宽度 * √(目标大小 / 图片当前大小)
// 新高度 = 原始高度 * √(目标大小 / 图片当前大小)
// 宽高同比例调整
// 宽度 > 最大限宽 -> 重置尺寸
if (width > config.maxWidth) {
const ratio = config.maxWidth / width
width = config.maxWidth
height = height * ratio
}
// 高度 > 最大限高度 -> 重置尺寸
if (height > config.maxHeight) {
const ratio = config.maxHeight / height
width = width * ratio
height = config.maxHeight
}
// 获取canvas元素
const query = wx.createSelectorQuery()
let dom = query.select(`#${canvasId}`)
dom.fields({
node: true,
size: true
})
.exec((res) => {
// Canvas 对象
const canvas = res[0].node
// 渲染上下文
const ctx = canvas.getContext('2d')
// 根据设备像素比处理尺寸 = 大小 * 设备像素
const dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = width * dpr
canvas.height = height * dpr
ctx.scale(dpr, dpr)
//创建img对象
let img = canvas.createImage();
img.src = file.path; // 给图片添加路径
//图片加载完毕
img.onload = function () {
// 将图片绘制到 canvas
ctx.drawImage(img, 0, 0, width, height)
// 生成图片
wx.canvasToTempFilePath({
canvas,
x: 0,
y: 0,
destWidth: width,
destHeight: height,
success(res) {
resolve(res); // 生成临时文件路径
}
})
}
})
})
return ctxInfo
} catch (err) {
console.log(err);
}
},
顺带再加一个解析上传图片的方法,方便我们进行转换
//获取图片信息
async getImgInfo(tempFilePath) {
try {
let image = await new Promise((resolve, reject) => {
wx.getImageInfo({
src: tempFilePath,
success(res) {
let imgInfo = {
type: res.type,
height: res.height,
width: res.width,
path: res.path
}
resolve(imgInfo)
},
fail(err) {
reject(err)
}
})
})
return image
} catch (err) {
console.log(err);
}
},
希望能为你带来帮助