开题
前几天接到个需求,长按图片保存到相册,该图片上有用户头像和昵称以及对应的二维码;那这就不能直接当作图片来操作了,要先把整体图片画出来;我当时用的是canvas。效果图如下:
canvas drawImage
用canvas画图主要使用dramImage API,不太清楚的同学可以区MDN看看:developer.mozilla.org/zh-CN/docs/…
主要是用到图片URL,相对于左上角的x,y坐标以及image在canvas上绘制的宽高。
开始画图
那我们开始行动了,先在html上写个canvas标签:
<canvas
canvas-id="shareCanvas"
class="canvas"
bindlongpress="saveImg"
catchtouchmove="true"
style="height: {{canvasHeight + 'rpx'}};width: {{canvasWidth + 'rpx'}};">
</canvas>
在微信小程序上画图先要把图片路径保存到本地,这里我们可以使用wx.getImageInfo或者wx.downloadFile将图片转为本地。考虑到我们要操作多个图片,这里对这些API进行封装:
getImageInfo(src) {
return new Promise((resolve, reject) => {
wx.getImageInfo({
src,
success: (res) => resolve(res),
fail: (res) => reject(res)
})
});
}
如果你要使用downloadFile也可以,封装方法和上面一样。 封装好了那么我们可以开始画图了,这里需要三张图片,对应的代码如下:
Promise
.all([
this.getImageInfo('https://cyt-resource.oss-cn-shanghai.aliyuncs.com/wximg/qrcode_bg.jpg'),
this.getImageInfo(this.data.userInfo.avatarUrl),
this.getImageInfo(this.data.qrCodeUrl)
])
.then((res) => {
const ctx = wx.createCanvasContext('shareCanvas');
ctx.drawImage(res[0].path, 0, 0, 图片宽度, 图片高度);
ctx.fillStyle = 'rgb(168, 88, 126)'; // 字体颜色
ctx.setFontSize(12); // 字体大小
ctx.fillText(this.data.userInfo.nickname, 相对于左上角的x坐标, 相对于左上角的y坐标);
ctx.drawImage(res[1].path, x坐标, y坐标, 宽, 高);
ctx.drawImage(res[2].path, x, y, width, height);
ctx.draw();
this.setData({
isDrawnImg: true
});
})
.catch((e) => {
});
在这里要说个需要注意的坑,将图片保存到本地需要在小程序后台的downloadFile域名配置里配置好对应的域名,一个都不能落, 比如微信头像需要在downloadFile合法域名配置里加入https://wx.qlogo.cn; 另外需要提醒大家,在微信开发者工具里调试的话尽量不要开不校验合法域名那个选项,即
不然就会出现在调试模式下都是好的,但是真机不开调试就没有效果了。而且不好排查错误。优化
由于canvas画图需要时间,那我们可以在等待时加个loading效果,在生成或者失败时隐藏loading,失败时还需要提示
wx.showLoading({
title: '图片生成中...'
});
wx.hideLoading();
wx.showToast({
title: '图片生成失败'
});
保存图片到相册
这里使用canvasToTempFilePath API,代码如下:
saveImg () {
wx.canvasToTempFilePath({
canvasId: 'shareCanvas',
success: (res) => {
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: (res) => {
wx.showToast({
title: '保存成功'
});
},
fail: (res) => {
this.authorizeToWritePhotosAlbum();
}
})
}
})
},
这里有个失败时候的操作,主要是因为取消授权后就不能使用了,这里要给个提示,让用户可以再次选择授权进行图片保存,方法如下:
// 授权保存图片至相册
authorizeToWritePhotosAlbum () {
wx.showModal({
title: '提示',
content: '需要您授权保存相册',
showCancel: false,
success: (res) => {
wx.openSetting({
success: (res) => {
if (settingdata.authSetting['scope.writePhotosAlbum']) {
wx.showModal({
title: '提示',
content: '获取权限成功,再次点击图片即可保存',
showCancel: false,
});
} else {
wx.showModal({
title: '提示',
content: '获取权限失败,将无法保存到相册哦~',
showCancel: false,
});
}
}
})
}
});
},
至此,画图以及保存到相册的问题都有解决了。那么如果我们需要适配呢,图片需要自适应。在微信小程序我们可以使用rpx进行自适应:可以看看文档 developers.weixin.qq.com/miniprogram…
自适应
因为drawImage里面的单位都是px,且不能更改,那我们应该怎么进行自适应。可以根据设置的 设备屏幕/750*自己设置的自适应宽度(单位为rpx),比如设置宽度为600rpx,那么在drawImage里就是设备屏幕/750*600;要获取屏幕高度直接调用wx.getSystemInfo就行了,取返回结果的screenWidth;文字大小,小图片的x,y坐标都可以通过这个方法进行自适应。
结题
我当时主要是域名配置忘了,坑了自己,然后就是授权问题(关闭后无法保存,自己懵了,没考虑到);希望大家都能注意下,写的不好的地方希望大家提出来,一大早写的比较匆忙,😄