业务需求,需要使用JS将url链接转为二维码图片。查到可以使用qrcodejs2传入内容、大小获得一个画布上的二维码。但是canvas标签在移动端上无法使用长按识别的功能,所以还需要把canvas对象转换为图片img标签。
网上找到的相关资料大多是通过html2canvas来将二维码转为图片的,但通过这种方法,总有一些奇奇怪怪的问题,比如有时候明明转成了base64,但是页面不显示。后来还是选择直接转为image,使用起来也更灵活。
首先安装qrcodejs2:
npm install qrcodejs2 --save
可以参考使用文档:
需要注意的一些踩坑点:
qrcode()生成方法,不能写在created()中调用,因为页面必须先渲染后再生成二维码。初始化时放在mounted钩子中,并延迟300批量生成二维码时,虽然传入了不同的内容值,出现了页面二维码显示重复,后台输出其实是生成了不同二维码的。原因是生成的二维码挂在了同一个div上,所以批量生成的时候需要传入id值!!!!如果传入的宽高值小,生成的二维码可能会出现不清晰的情况,最好的解决办法的生成二维码时放大,再使用css缩小。比如说想要一个80*80的二维码图片,可以传入height:400,width:400,再在标签外部使用css设置宽高值。
解决方法参考了:解决生成二维码长字符串显示模糊问题不要在二维码的div上设置宽高!不要在二维码的div上设置宽高!不要在二维码的div上设置宽高!否则会和第三点使用css设置宽高值冲突哈哈哈。
这里直接放上封装好的子组件了,qrcodeimg.js:
<template>
<div>
<img v-if="imgData != ''" :src="imgData" />
<div :id="qrid" class="qrcode" v-show="imgData == ''"></div>
</div>
</template>
<script>
import QRCode from "qrcodejs2" // 引入qrcode
export default {
name: "QrCodeImg",
props: ["qrid", "qrContent", "qrWidth", "qrHeight"],
data() {
return {
imgData: "",
}
},
watch: {
//监听二维码内容值的变化,重新生成二维码
qrContent: function (val) {
this.qrcode()
},
},
created() {},
mounted() {
setTimeout(() => {
this.qrcode()
}, 300)
},
methods: {
qrcode() {
this.$nextTick(() => {
document.getElementById(this.qrid).innerHTML = "" //否则每生成一次,上次的还存在,都会多一个二维码
//要先生成div再生成二维码,否则Cannot read properties of undefined (reading 'appendChild')
new QRCode(this.qrid, {
text: this.qrContent,
//text为转换为二维码的文本,可以是所有东西:图片、文本、电话、链接等等
width: this.qrWidth, //生成二维码的宽度
height: this.qrHeight, //生成二维码的高度
colorDark: "#333333", // 二维码颜色
colorLight: "#F8F8FF", //二维码背景颜色
})
})
var canvasobj = document.getElementsByTagName("canvas")[0]
// 将转换后的img标签插入到html中
var img = this.CanvasToImage(canvasobj)
this.imgData = img.src
},
CanvasToImage(canvas) {
//从canvas中提取图片image,新建image对象
var image = new Image()
// canvas.toDataURL 返回Base64编码的URL
image.src = canvas.toDataURL("image/jpg")
return image
},
},
}
</script>
<style lang="scss" >
</style>
父组件调用qrcodeimg.js如下:
<template>
<div class="container" id="app">
<div id="qrcodeArea">
//生成单个二维码时可以固定id值
<QrCodeImg
:qrid="'currentQr'"
:qrContent="qrContent"
:qrHeight="qrHeight"
:qrWidth="qrWidth"
/>
</div>
//批量生成二维码时需要动态传入id!!
<el-table border :data="tableList" class="tableBox">
<el-table-column label="二维码" width="100px">
<template slot-scope="scope">
<div id="qrcodeArea">
<QrCodeImg
@dblclick.native="qrcodedoubleClick(scope.$index)"
:qrid="scope.row.id"
:qrContent="scope.row.query_prod_entry"
:qrHeight="qrHeight"
:qrWidth="qrWidth"
/>
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import QrCodeImg from "../../components/QrCodeImg/QrCodeImg.vue"
export default {
components: {
QrCodeImg,
},
data() {
return {
qrWidth: 400,
qrHeight: 400,
qrContent: "https://www.baidu.com/",
}
},
computed: {},
watch: {},
mounted() {},
methods: {},
created() {},
}
</script>
<style lang="scss">
#qrcodeArea img {
height: 80px;
width: 80px;
}
</style>