最近在做一个Vue3移动端项目,有涉及到浏览器实现扫一扫功能,实现的效果如下图
实现原理
- 这里我们使用的是
jsQR库
- 安装
npm install jsqr -D
- 使用
// 一定要是在https环境下才能使用jsqr
// 具体可以在vite.config.ts的defineConfig里配置server: {https: true}
import jsQR from 'jsqr'
- 创建生成
canvas插入html标签
setDatas() {
if (origin.indexOf('https') === -1) {
// 判断是否为https环境
alert('请在 https 环境中使用本插件。')
}
const windowWidth = window.screen.availWidth
const windowHeight = window.screen.availHeight
this.canvasWidth = windowWidth
this.canvasHeight = windowHeight
this.$nextTick(() => {
this.video = document.createElement('video')
this.c = document.createElement('canvas')
this.c.id = 'c'
this.c.width = this.canvasWidth
this.c.height = this.canvasHeight
this.c.style.width = '100%'
document.querySelector('.canvasBox').append(this.c)
this.openScan()
})
}
- 使用
MediaDevices.getUserMedia()API调用本地摄像头实现录像以及拍照功能
openScan() {
const videoParam = {
audio: false,
video: {
// 调用后摄像头
facingMode: {exact:'environment'},
width,
height
}
}
navigator.mediaDevices
.getUserMedia(videoParam)
.then((stream) => {
this.video.srcObject = stream
this.video.setAttribute('playsinline', true)
this.video.play()
// 浏览器内置方法
requestAnimationFrame(this.tick);
[this.track] = stream.getVideoTracks()
setTimeout(() => {
// 控制是否关闭闪光灯
this.isUseTorch = this.track.getCapabilities().torch || null
}, 500)
})
.catch((err) => {
alert('设备不支持,请检查是否允许摄像头权限')
console.log(err)
})
}
- 通过
jsQR拿到二维码或条形码里的内容
tick() {
if (this.video.readyState === this.video.HAVE_ENOUGH_DATA) {
this.canvasHeight = this.video.videoHeight
this.canvasWidth = this.video.videoWidth
this.c.width = this.canvasWidth
this.c.height = this.canvasHeight
if (this.canvas2d === undefined) {
this.canvas2d = this.c.getContext('2d')
}
this.canvas2d.drawImage(
this.video,
0,
0,
this.canvasWidth,
this.canvasHeight
)
const imageData = this.canvas2d.getImageData(
0,
0,
this.canvasWidth,
this.canvasHeight
)
const code = jsQR(imageData.data, imageData.width, imageData.height, {
inversionAttempts: 'dontInvert'
})
if (code) {
this.drawLine(
code.location.topLeftCorner,
code.location.topRightCorner,
'#FF3B58'
)
this.drawLine(
code.location.topRightCorner,
code.location.bottomRightCorner,
'#FF3B58'
)
this.drawLine(
code.location.bottomRightCorner,
code.location.bottomLeftCorner,
'#FF3B58'
)
this.drawLine(
code.location.bottomLeftCorner,
code.location.topLeftCorner,
'#FF3B58'
)
if (code.data) {
this.getQrCode(code.data)
}
}
}
requestAnimationFrame(this.tick)
},
getQrCode(val) {
// 这里 val 就是二维码的内容,这里可以根据自己项目的需求处理内容
alert(JSON.stringify(val))
}