微信小程序生成海报中二维码-----长按识别不了问题及处理方案

> 问题描述:
小程序某个页面中点击按钮,想要生成带有二维码的图片,后续保存本地。生成图片后转发微信中,后长按图片不会出现识别图中二维码的选项问题。

一年前写过一个分享页,当时大部分可以识别,只有偶尔某一次识别不出来,当时就没有解决,可产品还能过去。可最近写了一个新的页面也有二维码,生成图片逻辑是一套代码,可这次没有有一次成功的。你说这咋整,想偷懒还是过不去的,终究还是要为自己的懒惰付出,躲不过去的,如果不打算转行,还是别给自己留坑吧。填起来~~~~~~

对于生成海报的功能搜一搜遍地都是,在这里我就不展开说了,本篇就对二维码的绘制详细介绍下!

>问题处理重点:

  • 首先说下二维码生成绘制方式:有两种! 第一种方式就是用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()
      }
    })
  })
}

到目前为止全部说完! 有问题 欢迎大家评论交流点赞哦~~~~~ 一起踩坑


版权声明:本文为yongyafang123原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。