> 问题描述:
小程序某个页面中点击按钮,想要生成带有二维码的图片,后续保存本地。生成图片后转发微信中,后长按图片不会出现识别图中二维码的选项问题。
一年前写过一个分享页,当时大部分可以识别,只有偶尔某一次识别不出来,当时就没有解决,可产品还能过去。可最近写了一个新的页面也有二维码,生成图片逻辑是一套代码,可这次没有有一次成功的。你说这咋整,想偷懒还是过不去的,终究还是要为自己的懒惰付出,躲不过去的,如果不打算转行,还是别给自己留坑吧。填起来~~~~~~
对于生成海报的功能搜一搜遍地都是,在这里我就不展开说了,本篇就对二维码的绘制详细介绍下!
>问题处理重点:
- 首先说下二维码生成绘制方式:有两种! 第一种方式就是用canvas画出来(利用qrcode.js)。第二种将链接转成base64的链接,然后让图片展示链接(qrcode-base64)。两个JS代码百度可得,如需可私聊我。
第一种使用,上代码:
const QRCode = require('../utils/QRCode.js')
ctx.draw(true, () => {
// 画二维码
let qrCode = new QRCode("shareImg", { // shareImg是canvas标签中的canvas-id="shareImg"
width: 100 * fixWidth, // 二维码宽高,以及距离画布的顶部左边的定位距离
height: 100 * fixWidth,
left: 520 * fixWidth,
top: 1132 * fixWidth,
typeNumber: 2
})
qrCode.makeCode(qrStr, () => { // qrStr是二维码地址如:https://www.baidu.com
// 二维码画成功
setTimeout(() => {
// 生成图片
createImage(that) // 继续执行生成图片操作wx.canvasToTempFilePath()
}, 300)
})
})
完工!这也就是我一年前的使用方式,本来也是好好地。可这次怎么都不行了。百度后知道了,因为第一次的时候,页面地址比较短,而且UI二维码图片比较大。但是这一次,很长的链接,二维码大小又变小了。奈何生成的二维码特别密集,手机根本识别不出来,无奈前功尽弃了,只能换其他的技术方案。 这也就是为什么我同一个方法效果不同的原因了。这种方式的清晰度和图片的URL及UI大小都有关系。所以如果和我遇到相同问题的同学,如果想快速解决上线,就可以把二维码UI调大,地址变短;这就几分钟就可以提交审核,后面我们在去研究其他方法(方法二)。但是目前这个大小和清晰度的关系我不是很清楚,有同学知道的可以告知一下,非常感谢!
接下来我们来研究第二种比较稳的方式,形成base64文件。
这种方式确实相对于第一种方式来说太棒了,即使二维码UI很小也能识别出来呢。
------原理:利用qrcode-base64 将二维码的URL链接,转成base64;因为小程序不能直接显示base64,所以接下来我们就利用创建读写流wx.getFileSystemManager()把base64通过writeFile写入本地,获得到一个临时文件地址;然后drawImage绘制出来就可以了。
下面我们就来看下他的代码实现:
const QR = require('../utils/weapp-qrcode.js')
var base64Data = QR.drawImg(qrStr, { // 二维码地址URL
typeNumber: 4,
errorCorrectLevel: 'M',
size: 500
})
// console.log(base64Data); // base64地址
/* 创建读写流 */
const fs = wx.getFileSystemManager()
const times = new Date().getTime()
const codeimg = wx.env.USER_DATA_PATH + '/' + times + '.png'
/* 将base64图片写入 */
fs.writeFile({
filePath: codeimg,
data: base64Data.slice(22), /* 数据流 */
encoding: 'base64',
success: () => {
ctx.drawImage(codeimg,520 * fixWidth, 1132 * fixWidth,50 * fixWidth, 50 * fixWidth)
console.log(codeimg);
ctx.draw(true, () => {
setTimeout(() => {
// 生成图片
createImage(that)
}, 300)
})
},
fail(res) {
console.error(res)
}
})
好了。到目前为止,可以把二维码大小改小,二维码也可以识别无误了。本以为万事大吉了。结果看网友说writeFile写入是有一定的空间大小的,如果一直写入到达一定空间后会写入不进去,就会报错。所以需要实时清理。那好吧,为了以防万一我们就在保存图片成功后,调用下清除函数removeSave() 去清空下内存。
下面是清缓函数代码:(原理:首先用FileSystemManager.readdir来拿到文件列表,再通过FileSystemManager.unlink把文件删掉)
// 把写入的文件删除,防止超过最大范围而无法写入,报错
const removeSave = () =>{
return new Promise((resolve)=>{
const fsm = wx.getFileSystemManager(); //文件管理器
fsm.readdir({ // 获取文件列表
dirPath: wx.env.USER_DATA_PATH,// 当时写入的文件夹
success(res){
console.log(res);
res.files.forEach((el) => { // 遍历文件列表里的数据 (把不是.png后缀的过滤掉)
if(el.includes('.png')){
// 删除存储的垃圾数据
fsm.unlink({
filePath: `${wx.env.USER_DATA_PATH}/${el}`, // 这里注意。文件夹也要加上,如果直接文件名的话会无法找到这个文件
fail(e){
console.log('readdir文件删除失败:',e)
}
});
}
})
resolve()
}
})
})
}
到目前为止全部说完! 有问题 欢迎大家评论交流点赞哦~~~~~ 一起踩坑