插件 html5-qrcode npm地址
html5-qrcode是一个基于JavaScript 轻量级和跨平台的扫码插件。允许用户使用摄像头扫描二维码,并且解析为文本或者url。
- 支持扫描不同类型的二维码和条形码
- 支持不同的平台,Android、IOS、Windows、MacOs或者linux
- 支持不同的浏览器,Chrome、Safari、Edge等
- 支持扫描本地文件
访问摄像头涉及用户隐私,所以访问环境必须在https下
实现(该代码环境基于vue3)
-
安装依赖
npm install html5-qrcode
-
引入
javascriptimport { Html5Qrcode } from 'html5-qrcode'
-
使用
-
setup数据
phpconst state = reactive({ html5QrCode: null, fileList:[] })
-
判断当前环境下是否有摄像头
scssHtml5Qrcode.getCameras() .then(devices =>{ if(devices &&devices.length){ // 当前环境下能识别出摄像头,并且摄像头的数据可能不止一个 state.html5QrCode = new Html5Qrcode('reader') // reader 放置扫码功能的元素ID startInit() } }) .catch(() =>{ // 摄像头无访问权限 })
-
扫码
iniconst startInit = () =>{ state.html5QrCode.start( // environment后置摄像头 user前置摄像头 {facingMode:'environment'}, { fps:1, // 可选,每n秒帧扫描一次 qrbox:{ width:250, height:250 } // 扫描的 UI框 }, (decodedText, decodedResult) =>{ // 扫描结果 } ) .catch((err) =>{ // 扫码错误信息 let message = '' if(typeof err == 'string'){ message = '识别失败' }else { if (err.name == 'NotAllowedError') { message = '您需要授予相机访问权限!' } if (err.name == 'NotFoundError') { message = '这个设备上没有摄像头!' } if (err.name == 'NotSupportedError') { message = '摄像头访问只支持在安全的上下文中,如https或localhost!' } if (err.name == 'NotReadableError') { message = '相机被占用!' } if (err.name == 'OverconstrainedError') { message = '安装摄像头不合适!' } if (err.name == 'StreamApiNotSupportedError') { message = '此浏览器不支持流API!' } } }) }
-
-
停止扫码
javascriptconst stop = () => { state.html5QrCode .stop() .then((ignore) => { console.log('停止扫码', ignore) }) .catch((err) => { console.log(err) showToast('停止扫码失败') }) }
-
识别本地文件
javascriptconst dealSelectFiles = () => { try { window.qrcode.callback = (result) => { // 识别成功 } // get select files. let file = state.fileList[0].file var reader = new FileReader() reader.onload = (function () { return function (e) { window.qrcode.decode(e.target.result) } })(file) reader.readAsDataURL(file) } catch (error) { // 识别失败 } }
-
在离开页面时要停止扫码功能
scssonUnmounted(() => { //扫描设备是否在运行 if (state.html5QrCode.isScanning) { stop() } })
完整代码
xml
<template>
<div class="scanCode">
<div class="container">
<div class="qrcode">
<div id="reader"></div>
</div>
</div>
<div class="btn">
<div class="left-back">
<van-icon name="arrow-left" @click="clickBack" />
</div>
<div class="right-file">
<van-uploader v-model="fileList" :preview-image="false" :after-read="dealSelectFiles">
<van-icon name="photo-o" />
</van-uploader>
</div>
</div>
</div>
</template>
<script>
import { reactive } from 'vue'
import { defineComponent, toRefs, onMounted, onUnmounted } from 'vue'
import { Html5Qrcode } from 'html5-qrcode'
import { showToast, } from 'vant'
export default defineComponent({
setup() {
const state = reactive({
html5QrCode: null,
fileList: [],
})
const start = () => {
state.html5QrCode
.start(
{ facingMode: 'environment' },
{
fps: 1,
qrbox: { width: 250, height: 250 }
},
(decodedText, decodedResult) => {
console.log('decodedText', decodedText)
console.log('decodedResult', decodedResult)
}
)
.catch((err) => {
console.log('扫码错误信息', err)
let message = ''
// 错误信息处理仅供参考,具体描述自定义
if (typeof err == 'string') {
message = '二维码识别失败!'
} else {
if (err.name == 'NotAllowedError') {
message = '您需要授予相机访问权限!'
}
if (err.name == 'NotFoundError') {
message = '这个设备上没有摄像头!'
}
if (err.name == 'NotSupportedError') {
message = '摄像头访问只支持在安全的上下文中,如https或localhost!'
}
if (err.name == 'NotReadableError') {
message = '相机被占用!'
}
if (err.name == 'OverconstrainedError') {
message = '安装摄像头不合适!'
}
if (err.name == 'StreamApiNotSupportedError') {
message = '此浏览器不支持流API!'
}
}
})
}
const getCameras = () => {
Html5Qrcode.getCameras()
.then((devices) => {
if (devices && devices.length) {
state.html5QrCode = new Html5Qrcode('reader')
start()
}
})
.catch((err) => {
showToast({
message: '摄像头无访问权限!',
duration: 3000
})
}
const stop = () => {
state.html5QrCode
.stop()
.then((ignore) => {
console.log('停止扫码', ignore)
})
.catch((err) => {
console.log(err)
showToast('停止扫码失败')
})
}
const dealSelectFiles = () => {
try {
window.qrcode.callback = (result) => {
showToast('成功了,结果是:' + result)
}
// get select files.
let file = state.fileList[0].file
var reader = new FileReader()
reader.onload = (function () {
return function (e) {
window.qrcode.decode(e.target.result)
}
})(file)
reader.readAsDataURL(file)
} catch (error) {
showToast({
message: '图片识别失败!',
duration: 3000
})
}
}
onMounted(() => {
getCameras()
})
onUnmounted(() => {
//扫描设备是否在运行
if (state.html5QrCode.isScanning) {
stop()
}
})
return {
...toRefs(state),
getCameras,
dealSelectFiles,
}
}
})
</script>
<style lang="scss" scoped>
.scanCode {
height: 100vh;
display: flex;
flex-direction: column;
background: rgba(0, 0, 0);
}
.container {
height: 90vh;
position: relative;
width: 100%;
}
.qrcode {
height: 100%;
}
#reader {
top: 50%;
left: 0;
transform: translateY(-50%);
}
.btn {
flex: 1;
padding: 3vw;
display: flex;
justify-content: space-around;
color: #fff;
font-size: 8vw;
align-items: flex-start;
}
</style>