react h5实现扫一扫功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | /* * * 1、listVideoInputDevices * 获取摄像头设备得到一个摄像头设备数组,根据摄像头的id选择使用的摄像头 * 2、decodeFromInputVideoDeviceContinuously() * 第一个参数为前面数组得到的摄像头的id,根据传入的摄像头id 选择摄像头扫描 ,id为null时 默认使用面向环境的摄像头 */ import React, { useEffect } from 'react' import { Toast } from 'antd-mobile' import { BrowserMultiFormatReader } from '@zxing/library' import "./index.less" export default function ScanCode (props) { const codeReader = new BrowserMultiFormatReader() useEffect(() => { openScan() return (() => { destoryScan() }) }, []) const destoryScan = () => { codeReader.reset(); codeReader.stopContinuousDecode(); } const openScan = async () => { codeReader.listVideoInputDevices().then((videoInputDevices) => { console.log(videoInputDevices, 'videoInputDevices' ); // 获取第一个摄像头设备的名称 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); }) } const decodeFromInputVideoFunc = (firstDeviceId) => { // firstDeviceId 为null 时默认选择面向环境的摄像头 codeReader.decodeFromVideoDevice(firstDeviceId, 'video' , (result, err) => { if (result) { Toast.show({ content: "扫描成功" }) props.getResult(result.text) destoryScan() } if (err) { // console.error(err); } }) } const backScan = () => { props.getResult( '返回' ) destoryScan() } return ( <div className= "page-scan" > <div className= 'back' onClick={backScan}><img src={require( "../../assets/img/arrow_back.png" ). default } alt= "" /> 返回</div> <div className= "scan-box" > <video id= "video" className= "scan-video" autoplay></video> <div className= "qr-scanner" > <div className= "box" > <div className= "line" ></div> <div className= "angle" ></div> </div> </div> <div className= "scan-tip" >扫描条形码</div> </div> </div> ) } |
1 | ./index.less文件 |
.scan-box { position: fixed; top: 0; left: 0; height: 100%; width: 100vw; background-image: linear-gradient( 0deg, transparent 24%, rgba(32, 255, 77, 0.1) 25%, rgba(32, 255, 77, 0.1) 26%, transparent 27%, transparent 74%, rgba(32, 255, 77, 0.1) 75%, rgba(32, 255, 77, 0.1) 76%, transparent 77%, transparent ), linear-gradient( 90deg, transparent 24%, rgba(32, 255, 77, 0.1) 25%, rgba(32, 255, 77, 0.1) 26%, transparent 27%, transparent 74%, rgba(32, 255, 77, 0.1) 75%, rgba(32, 255, 77, 0.1) 76%, transparent 77%, transparent ); background-size: 3rem 3rem; background-position: -1rem -1rem; } .back{ font-size: 24px; color: #fff; font-weight: bolder; line-height: 50px; display: flex; align-items: center; z-index: 9999; position: fixed; top: 30px; left: 20px; img{ width: 40px; height: 40px; } } .scan-video { height: 100vh; width: 100vw; object-fit: cover; } .qr-scanner .box { width: 500px; height: 500px; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); overflow: hidden; border: 0.1rem solid rgba(0, 255, 51, 0.2); background: url('http://resource.beige.world/imgs/gongconghao.png') no-repeat center center; } .qr-scanner .line { height: calc(100% - 2px); width: 100%; background: linear-gradient(180deg, rgba(0, 255, 51, 0) 43%, #00ff33 211%); border-bottom: 3px solid #00ff33; transform: translateY(-100%); animation: radar-beam 2s infinite alternate; animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99); animation-delay: 1.4s; } .qr-scanner .box:after, .qr-scanner .box:before, .qr-scanner .angle:after, .qr-scanner .angle:before { content: ""; display: block; position: absolute; width: 3vw; height: 3vw; border: 0.2rem solid transparent; } .qr-scanner .box:after, .qr-scanner .box:before { top: 0; border-top-color: #00ff33; } .qr-scanner .angle:after, .qr-scanner .angle:before { bottom: 0; border-bottom-color: #00ff33; } .qr-scanner .box:before, .qr-scanner .angle:before { left: 0; border-left-color: #00ff33; } .qr-scanner .box:after, .qr-scanner .angle:after { right: 0; border-right-color: #00ff33; } @keyframes radar-beam { 0% { transform: translateY(-100%); } 100% { transform: translateY(0); } } .scan-tip { width: 100vw; text-align: center; margin-bottom: 5vh; color: white; font-size: 5vw; position: absolute; bottom: 50px; left: 0; color: #fff; } .page-scan { overflow-y: hidden; z-index: 999; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具