一、需求背景

在 VUE 开发的微信公众号项目中,有一个动态生成二维码的需求:根据后端传来的参数,动态生成二维码,用户长按动态生成的二维码,然后识别做相应操作。


二、BUG问题

二维码的生成采用的是第三方库 qrcodejs2,功能实现后,测试发现,在苹果 IOS 系统中长按可以正常识别,而在安卓手机长按则无法识别。


三、原因分析

第三方库 qrcodejs2 生成二维码时,它会在我们指定 div 盒子内动态生成两个元素,分别是 canvas 和 img,如下图所示:

qrcodejs2.jpg


上图是在浏览器测试时的截图,可以看到 canvas 处于隐藏(display: none;)状态,img 处于显示(display: block;)状态。这种状态是没问题的,因为只有长按 img 图片才会弹出识别按钮,既然安卓手机长按无法弹出识别按钮,说明安卓手机展示的不是 img 元素,而是 canvas 元素。


四、解决方案

既然只有 img 元素才可以被识别,那么我们只要保证不让其展示 canvas 画布,始终展示 img 就可以了。具体代码如下:

<!-- 隐藏原来存放二维码的 div -->
<div id="qrcode" style="display: none;"></div>

<!-- 添加一个新的div,用来展示 canvas 转换的 base64 图片 -->
<div style="text-align: center;">
    <img :src="qrcodeimg" alt="" width="200" height="200" v-show="qrcodeimg">
</div>


我们在指定的 div#qrcode 下面,再创建了一个div,并把原来装二维码的 div#qrcode 进行隐藏,然后生成二维码之后,我们获取 div#qrcode 里的 canvas 元素,并将拿到的 canvas 转为 base64 图片,然后展示在下面新创建的 div 中。这样处理之后,不管什么情况,始终展示的都是 img 图片了。

// 生成二维码
new QRCode("qrcode", {
    width: 200,
    height: 200,
    text: this.payCode
});

// 生成二维码之后,获取canvas元素
let qrcodeEle = document.getElementById("qrcode")
let cvs = qrcodeEle.querySelector('canvas')
this.qrcodeimg = cvs.toDataURL('image/png')
本文最后更新于 2023-11-14 20:13:48微信开发
天生我材必有用,千金散尽还复来~~
作者:鄢云峰 YYF声明:转载请注明文章出处地址:https://yanyunfeng.com/article/22
评论
提交
Comments | 8 条评论
Demon2023-11-15 10:44:02
#1 回复
感谢作者分享,简单且好用
鄢云峰站长2023-11-15 10:48:37
#2 回复
@Demon 不谢,对你有帮助就好😄
不羁2023-11-15 10:51:31
#3 回复
这么正确的而且简单的方法搜索词条居然那么靠后。真是醉了。
鄢云峰站长2023-11-15 10:54:53
#4 回复
@不羁 谢谢认可!
张荫2023-11-28 15:37:30
#5 回复
我也遇到这个问题了 抱着试一试的想法百度了下搜到了您的帖子完美解决了我的问题 nice😘😘😘
鄢云峰站长2023-11-28 21:10:09
#6 回复
@张荫 很高兴有帮助到你😄
刘涛2024-07-29 10:18:53
#7 回复
感谢
7-242024-07-29 10:39:32
#8 回复
看了一下qrcode的源码,是因为有一个安卓低版本的判断,低版本安卓不执行 Canvas.toDataURL('image/png') 可能是不兼容吧。然后就是qrcode中获取系统安卓版本号的那个正则出现了问题,导致高版本安卓版本号无法获取被判断为了低版本安卓。找到 _getAndroid 这个方法,重写一下里面的正则表达式就解决这个问题了。 var aMat = sAgent.toString().match(/android ([0-9]\.[0-9])/i) 改为 var aMat = sAgent.toString().match(/Android ([0-9\.]*)/)