前言
在上一篇文章,我们介绍了使用 qrcodejs
进行二维码的生成,这篇文章我们来了解一下 二维码的解析
,对于 API调用工程师
来说,学会 调用
每一个 api
是我们应尽的责任和义务。
介绍
解析二维码,我们将用到两个插件,llqrcode
和 jsqr
,为什么用两个插件呢,原因在于二维码解析可能会失败,当我们使用第一个插件解析失败之后,使用第二个插件再次解析,极大的提高二维码解析的成功率。
本篇文章同样以一个 html
为例,点击按钮选择图片,监听回调这里就不做介绍,主要从选择完图片之后 开始解析
说起。
开始
下载引入插件
首先我们引入这两个插件,打开 npm官网
,搜索 llqrcode
,
image.png
点击 code
,打开 index.js
文件:
image.png
将里面的代码 copy
下来,在你 html
同级新建一个 llqrcode.js
文件,将复制的代码粘贴进去:
image.png
接下来下载第二个插件 jsqr
, 同样打开 npm官网
,搜索 jsqr
,打开 /jsqr/dist/jsQR.js
文件
image.png
将里面的代码 copy
出来,粘贴在 llqrcode.js
同级的 jsqr.js
文件中
image.png
最后在我们的 html
中引入这两个插件:
<script src="./llqrcode.js"></script>
<script src="./jsqr.js"></script>
第一次解析
需要先定义一个方法getObjectURL
,用来将 File
转为 blob
格式的临时路径,这段代码兼容了不同内核的浏览器,网上也都能找到,就不再详讲:
getObjectURL(file) {
let url = null;
if (window.createObjectURL != undefined) { // basic
url = window.createObjectURL(file);
} else if (window.URL != undefined) { // mozilla(firefox)
url = window.URL.createObjectURL(file);
} else if (window.webkitURL != undefined) { // webkit or chrome
url = window.webkitURL.createObjectURL(file);
}
return url;
},
定义一个解决解码结果中文乱码的方法:
function decodeStr(str) {
var out, i, len, c;
var char2, char3;
out = "";
len = str.length;
i = 0;
while (i < len) {
c = str.charCodeAt(i++);
switch (c >> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
// 0xxxxxxx
out += str.charAt(i - 1);
break;
case 12:
case 13:
// 110x xxxx 10xx xxxx
char2 = str.charCodeAt(i++);
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = str.charCodeAt(i++);
char3 = str.charCodeAt(i++);
out += String.fromCharCode(((c & 0x0F) << 12) |
((char2 & 0x3F) << 6) |
((char3 & 0x3F) << 0));
break;
}
}
return out;
}
假设现在有一个方法 selectFiles
,这是我们选择图片完成的回调,选择到的图片在事件参数 e.target.files
中:
function selectFiles(e){
const files = e.target.files;
}
循环所有的 files
,通过 getObjectURL
生成 临时url
,定义一个全局变量 allQr
,并把每一个 url
存储进去,再调用 qrcode.decode
来解码所有的二维码,:
function selectFiles(e){
const files = e.target.files;
for(let i = 0; i < files.length; i ++){
const url = getObjectURL(files[i]);
allQr.push(url);
qrcode.decode(url,e);
}
}
然后通过 qrcode.callback
来获取解码之后的结果,需要注意的是,这个回调是异步的,需要从回调参数里的path
和 allQr
的url进行关联:
qrcode.callback = async function (imgMsg,path) {
allQr.forEach(async url => {
if(url == path){
// 定义解码失败的标识
const errArr = ['error','Failed'];
if(errArr.indexOf(imgMsg.split(' ')[0]) == -1){
// 解码成功之后解决中文乱码
item.code = decodeStr(imgMsg);
}else{
// 解码失败,二次解码
// ...
}
}
})
}
接下来开始二次解码,使用 promise
封装一个解码方法
base64ToqR(data) {
return new Promise((resolve,reject) => {
const c = document.getElementById("qrcanvas");
const ctx = c.getContext("2d");
const img = new Image();
img.src = data;
img.onload = function() {
$("#qrcanvas").attr("width",img.width)
$("#qrcanvas").attr("height",img.height)
ctx.drawImage(img, 0, 0, img.width, img.height);
const imageData = ctx.getImageData(0, 0, img.width, img.height);
const code = jsQR(imageData.data, imageData.width, imageData.height, {
inversionAttempts: "dontInvert",
});
resolve(code);
};
})
},
在第一次解码失败的地方,调用二次解码方法:
qrcode.callback = async function (imgMsg,path) {
allQr.forEach(async url => {
if(url == path){
// 定义解码失败的标识
const errArr = ['error','Failed'];
if(errArr.indexOf(imgMsg.split(' ')[0]) == -1){
// 解码成功之后解决中文乱码
item.code = decodeStr(imgMsg);
}else{
// 解码失败,二次解码
const {data} = await base64ToqR(url);
if(data){
item.code = decodeStr(data);
}else{
item.errmsg = '检测不到二维码或二维码识别率低'
}
}
})
更大程度上保证了解码的成功率。
最后,我是用这两个插件,做了这么一个批量解码的小 demo
,欢迎大家体验:批量解码
结语
我是一名前端程序员,但不止于前端,如果你对上述文章有所见解,欢迎评论区讨论,大家一起学习,一起进步~,最后,再次感谢你能看到这里。