主题
平台二维码生成以及需要注意事项
问题原因
- 网页端生成的二维码,部分功能中存在移动端和网页端进行交互的场景,由于公司移动端使用的二维码识别库,识别率不高,经常会出现二维码识别失败的问题。所以我们在生成二维码的时候,需要将二维码的识别率提高。
解决方案
提高识别率的方法如下:
- 生成二维码的时候,添加logo或者文字有遮挡的情况,设置二维码的容错率。
- 生成二维码的时候,给二维码添加一个白色留边。
参考链接
实现代码
- 由于平台使用的是qrcodejs2二维码插件, 就以此为例,其他插件也可以参考。
vue
<template>
<el-dialog :title="title" :visible.sync="dialogVisible" v-dialog-loading="pageLoad" width="45em" center @closed="closed" :close-on-click-modal="false">
<div class="qr-code">
<el-row :gutter="10" class="qrcode-title">
<el-col>
<span>{{ subTitle }}</span>
</el-col>
</el-row>
<el-row :gutter="10" class="qrcode-photo">
<el-col>
<div id="qrcode" class="qrcode" ref="qrcode"></div>
</el-col>
</el-row>
</div>
<span slot="footer" class="dialog-footer">
<el-button class="lb-btn lb-btn-primary" @click="downloadQRCode()">保存二维码</el-button>
</span>
</el-dialog>
</template>
<script>
import QRCode from 'qrcodejs2';
export default {
name: 'QRCode',
props: {
title: { // 弹框标题
type: String,
required: true,
},
subTitle: { // 提示文字
type: String,
default: '',
},
},
data() {
return {
dialogVisible: false,
btnLoad: false,
pageLoad: false,
qrcode: {},
params: {},
};
},
methods: {
closed() {
this.btnLoad = false;
this.qrcode.clear(); // 清除二维码
this.params = {};
},
async open(item) {
this.dialogVisible = true;
this.params = item;
await this.$nextTick();
this.creatQrCode(this.params.text, true);
},
// 生成二维码
creatQrCode(text, haveLogo) {
this.$refs.qrcode.innerHTML = ''; //清除二维码方法一
this.qrcode = new QRCode(this.$refs.qrcode, {
text: text, //页面地址 ,如果页面需要参数传递请注意哈希模式#
width: 200,
height: 200,
colorDark: '#000000',
colorLight: '#ffffff',
correctLevel: QRCode.CorrectLevel.H, // 容错级别,可配置L M Q H H为最高
});
this.qrcode._el.title = '';
/*** 由于插件生成的二维码图片不带边框,所以需要自己添加一个白色边框,这里使用canvas重绘 ***/
// 获取插件生成的二维码canvas元素
var canvas = this.qrcode._el.getElementsByTagName('canvas')[0];
// 创建一个新的canvas元素,并设置它的宽度和高度,以及边框的宽度
var borderCanvas = document.createElement('canvas');
borderCanvas.width = canvas.width + 10; // 设置为比二维码canvas元素宽度多10个像素的宽度
borderCanvas.height = canvas.height + 10;// 设置为比二维码canvas元素高度多10个像素的高度
var ctx = borderCanvas.getContext('2d');
// 绘制白色背景
ctx.fillStyle = "#ffffff";
ctx.fillRect(0, 0, borderCanvas.width, borderCanvas.height);
// 将生成的二维码canvas元素绘制在新的canvas元素中心,形成边框
ctx.drawImage(canvas, (borderCanvas.width - canvas.width) / 2, (borderCanvas.height - canvas.height) / 2);
// 将生成的带有边框的二维码canvas元素插入到页面中
this.$refs.qrcode.appendChild(borderCanvas);
// 判断是否需要插入logo图标
if(haveLogo) {
// 二维码中心插入logo图标
let logo = new Image();
logo.setAttribute('crossOrigin', 'Anonymous');
logo.src = localStorage.webFileURL + '/resource/app/static/image/jgyl-logo.png';
logo.style.padding = '5px';
logo.onload = () => {
let qrImg = this.qrcode._el.getElementsByTagName('img')[0];
let canvas = this.qrcode._el.getElementsByTagName('canvas')[1];
canvas.style.display = 'inline-block';
let ctx = canvas.getContext('2d');
// 绘制logo图标白色边框
ctx.fillStyle = "#FFFFFF";
ctx.fillRect((210 - 210 / 3.7) / 2 - 4, (210 - 210 / 3.7) / 2 - 4, 210 / 3.7 + 8, 210 / 3.7 + 8)
// 设置logo的大小为二维码图片缩小3.7倍,第二与第三参数为logo的左上角坐标在二维码的位置
ctx.drawImage(logo, (210 - 210 / 3.7) / 2, (210 - 210 / 3.7) / 2, 210 / 3.7, 210 / 3.7)
qrImg.src = canvas.toDataURL();
qrImg.style.display = 'none'; // 隐藏原先插件生成的二维码图片
}
} else {
// 隐藏原先插件生成的二维码图片
let qrImg = this.qrcode._el.getElementsByTagName('img')[0];
setTimeout(() => { // 这里需要使用定时器,否则会出现无法设置 display 属性隐藏的情况
qrImg.style.display = 'none';
}, 50)
}
},
// 下载二维码
downloadQRCode() {
let canvas = this.qrcode._el.getElementsByTagName('canvas')[1]
let imgUrl = canvas.toDataURL('image/png');
let a = document.createElement('a');
a.href = imgUrl;
a.download = '二维码.png';
a.click();
}
},
};
</script>
<style lang="less" scoped>
.qr-code {
.qrcode-title {
margin-bottom: 1.5em;
text-align: center;
line-height: 2em;
color: #ccc;
}
.qrcode-photo {
.qrcode {
margin-bottom: 1em;
margin: auto;
height: 15em;
width: 15em;
}
margin-bottom: 1em;
/deep/ img {
margin: auto;
}
}
.qrcode-refresh-btn {
margin-bottom: 1em;
text-align: center;
.refresh-btn {
margin-right: 1em;
}
}
.qrcode-tips {
margin-bottom: 1em;
text-align: center;
line-height: 2em;
color: red;
.tips {
margin-left: 7em;
text-align: left;
}
.download-tips {
cursor: pointer;
}
}
}
</style>