安装包
npm i @zxing/library
/*
* 1、listVideoInputDevices
* 获取摄像头设备得到一个摄像头设备数组,根据摄像头的id选择使用的摄像头
* 2、decodeFromInputVideoDeviceContinuously 已不推荐使用-改用decodeFromVideoDevice
* 第一个参数为前面数组得到的摄像头的id,根据传入的摄像头id 选择摄像头扫描 ,id为null 时 默认使用面向环境的摄像头
*/
import React, { useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { BrowserMultiFormatReader } from '@zxing/library'
import { recordDetails } from '../../api'
import './index.less'
import { Toast } from 'react-vant'
export default function ScanCode() {
let num = 0
let timer
const navigate = useNavigate()
const codeReader = new BrowserMultiFormatReader()
useEffect(() => {
openScan()
return () => {
clearTimeout(timer)
codeReader.reset()// 组件销毁时重置关闭摄像头
}
}, [])
//调用摄像头
function openScan() {
codeReader.listVideoInputDevices().then((videoInputDevices) => {
// console.log('videoInputDevices', videoInputDevices)
// 默认获取第一个摄像头设备id
let firstDeviceId = videoInputDevices[0].deviceId
const videoInputDeviceslablestr = JSON.stringify(videoInputDevices[0].label)
//调用后置摄像头
if (videoInputDevices.length > 1) {
// 判断是否后置摄像头
if (videoInputDeviceslablestr.indexOf('back') > -1) {
firstDeviceId = videoInputDevices[0].deviceId
} else {
firstDeviceId = videoInputDevices[1].deviceId
}
}
decodeFromInputVideoFunc(firstDeviceId)
}).catch(err => { // console.error(err);
})
}
//开始扫码分析
function decodeFromInputVideoFunc(firstDeviceId) {
// firstDeviceId 为null 时默认选择面向环境的摄像头
codeReader.decodeFromVideoDevice(firstDeviceId, 'video',
async (result, err) => {
if (result) {
/**************扫码成功后做业务逻辑***********/
}
if (err) {
// console.error(err);
}
}
)
}
return (
<div id='scancode'>
<main>
<div className='code'>
<div className='hengxian' />
<video id="video" style={{ width: '100%' }} />
<div className='txt'>请调整扫描角度~</div>
</div>
</main>
<footer>
<div onClick={() => navigate('/recordlist')} className='cancel'>取消</div>
<div onClick={() => window.location.reload()}>重新扫描</div>
</footer>
</div>
)
}
自定义扫码样式index.less
#scancode {
height: 100vh;
background-color: #F6F7F8;
main {
display: flex;
justify-content: center;
padding-top: 20px;
.code {
width: 250px;
// height: 150px;
position: relative;
.hengxian {
width: 100%;
height: 3px;
background-color: #018FAD;
opacity: 0.5;
position: absolute;
top: -125px;
animation: 2s 1.5s move linear infinite;
}
@keyframes move {
0% { top: 0px; }
100% { top: 250px }
}
.txt {
text-align: center;
color: #21bfdf;
font-size: 14px;
}
}
}
footer {
margin-top: 50px;
display: flex;
justify-content: center;
div {
width: 120px;
height: 40px;
color: white;
background-color: #018FAD;
border-radius: 25px;
display: flex;
justify-content: center;
align-items: center;
}
.cancel {
background-color: white;
color: #018FAD;
border: 1px solid #018FAD;
margin-right: 40px;
}
}
}