前言
图片的合并有很广泛的应用,例如活动海报图,需要背景图片和二维码图片。在小程序中,有两种解决方案:
- 后端直接合并生成,通过接口获得;
- 前段利用canvas实现图片拼接并支持下载。
当批量处理的时候,后端返回的速度可能有些慢,用户体验不好,所以现在介绍下前端利用canvas实现的步骤,如果你当前也在做类似图片合并的功能,通过这篇文章互相交流,希望对你有所帮助,对我也是个提高的方式。
初始化canvas
微信小程序废弃了之前的canvas相关接口,现在设置type="2d"即可使用原生的相关的api。canvas api
<canvas type="2d" id="canvas"></canvas>
注意: 官方文档对于获取canvas实例的方式有所区别,页面和组件内的获取方式不同,以下为页面内的获取方式,其他可查阅微信官方文档(吐槽下,文档嫩不嫩写的再好点哇=。=)
const query = wx.createSelectorQuery()
query.select('#canvas').fields({ node: true, size: true }).exec((res) => {
const canvas = res[0].node
const ctx = canvas.getContext('2d')
// canvas实例和其context
this.setData({ canvas, ctx })
})
批量图片合并
从后端获得背景图片列表imageList数组和二维码图片链接qrcodeUrl字符串。
onLoad() {
// 通过接口获得的imageList, qrcodeUrl
this.setData({ imageList, qrcodeUrl },this.getMergeImgaes)
}
async getMergeImgaes() {
const finalImages = await Promise.all(this.drawImage())
// 获得批量合并生成后的图片数组,可以进行接下来的操作
// ...
}
注意: canvas的drawImage需要在图片对象的onload异步中使用,那对于批量来说,就需要思考,我首先要拿到二维码的图片对象,然后再遍历背景图片数组,与每一张图片合并后再返回新的图片,我们使用promise处理。
drawImage() {
const { imageList, qrcodeUrl, canvas, ctx } = this.data
const qrcodeImage = new Promise((resolve, reject) => {
// 小程序中使用createImage获得图片实例,而不是new Image()
const image = canvas.createImage()
image.src = qrcodeurl
image.onload = () => {
resolve(image)
}
})
// 接下来异步处理下图片的合并
let promiseList = []
for (let item of imageList) { // 为什么用for of,可以想想
let p = new Promise((resolve, reject) => {
qrcodeImage.then(qrcode => {
const image = canvas.createImage()
image.src = item
image.onload = () => {
canvas.width = image.width
canvas.height = image.height
// 批量处理,首先需要清除下画布再重新绘制
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.drawImage(image, 0, 0, canvas.width, canvas.height)
// 关于二维码或其他需要拼接的图片,首先确定下x,y的坐标
ctx.drawImage(qrcode, x, y, qrcode.width, qrcode.height)
// 将canvas的画布转为图片
resolve(canvas.toDataURL())
//wx.canvasToTempFilePath获得的是本地临时路径,在批量状态下可能会显示重复
}
})
})
promiseList.push(p)
}
return promiseList
}
后记
将多张图片合并成一张也是如此,很简单,本文主要考虑微信小程序环境中对图片进行批量合并处理的情况。另外值得一提的是,若是图片需要提高精度以减少锯齿感,可依据微信文档的处理方法即可。谢谢!