现象:
小程序生成二维码后,使用canvas绘制到画板,开发工具可以显示,真机无法显示
原因:
生成二维码插件生成的图是base64格式的,而canvas不支持base64图片的
解决方案:
1、删除本地同名文件
2、将base64图片,存储到本地,生成临时url
3、将本地图片绘制到canvas
具体实现:
1、删除本地同名文件
removeSave(FILE_BASE_NAME = 'tmp_base64src', format = 'jpg') {
return new Promise((resolve) => {
// 把文件删除后再写进,防止超过最大范围而无法写入
const fsm = uni.getFileSystemManager(); //文件管理器
const FILE_BASE_NAME = 'tmp_base64src';
const format = 'gif';
const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
fsm.unlink({
filePath: filePath,
success(res) {
console.log('文件删除成功');
resolve(true);
},
fail(e) {
console.log('readdir文件删除失败:', e);
resolve(true);
}
});
})
}
2、将base64图片,存储到本地,生成临时url(包含将base64和字节流转成本地文件)
base64ToSave(base64data, FILE_BASE_NAME = 'tmp_base64src') {
const fsm = uni.getFileSystemManager();
return new Promise((resolve, reject) => {
//format这个跟base64数据的开头对应
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || [];
if (!format) {
reject(new Error('ERROR_BASE64SRC_PARSE'));
}
const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
//const buffer = wx.base64ToArrayBuffer(bodyData);
fsm.writeFile({
filePath,
data: bodyData,
//data: base64data.split(";base64,")[1],
encoding: 'base64',
success() {
resolve(filePath);
},
fail() {
reject(new Error('ERROR_BASE64SRC_WRITE'));
},
});
});
}
3、将本地图片绘制到canvas
drawCardImg(codeImg) {
var remUnit = this.remUnit;
var canvasWidth = 16 * remUnit;
var canvasHeight = 16 * remUnit;
const ctx = uni.createCanvasContext('cardCanvas');
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
ctx.setFillStyle('#fff');
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
ctx.save();
ctx.drawImage(codeImg, 0, 0, canvasWidth, canvasHeight);
//恢复之前保存的绘图上下文。
ctx.restore();
ctx.draw(true, () => {
//一定要延时一下,总是不延时,我本人的手机生成的二维码还是图片有bug
setTimeout(() => {
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: canvasWidth,
height: canvasHeight,
destWidth: canvasWidth,
destHeight: canvasHeight,
canvasId: 'cardCanvas',
success: (res) => {
this.savedImgUrl = res.tempFilePath;
}
})
}, 700);
});
}
4、总流程
await this.removeSave();
var urlQR = await this.base64ToSave(base64Img);
if (urlQR) {
this.drawCardImg(urlQR);
}