当前位置: 首页 > news >正文

手机 浏览器调用摄像头扫描二维码Quagga

注:需用谷歌浏览器才能调用权限

1. 引入依赖:npm install @ericblade/quagga2

<template><el-button color="#188ae2" @click="handleScan" class="scan-btn" :disabled="isInitializing || isScanning">{{t('btn.scan') }}</el-button><!-- 条形码扫描器的占位符 --><div id="interactive" ref="interactiveRef" class="viewport" style="display: none;"></div></template><script setup>import { ref, onBeforeUnmount } from 'vue'
import Quagga from '@ericblade/quagga2'; // 引用
const interactiveRef = ref < HTMLElement | null > (null)
const isInitializing = ref(false)
const isScanning = ref(false)
const lastScanTime = ref(0)
let onDetectedHandler = null// 统一停止/清理
const stopScan = () => {try { Quagga.stop() } catch { }const el = interactiveRef.value || (document.querySelector('#interactive') || null)if (el) el.style.display = 'none'if (onDetectedHandler) {Quagga.offDetected(onDetectedHandler)onDetectedHandler = null}isScanning.value = falseisInitializing.value = false
}const handleScan = async () => {// 防抖:1s 内不重复触发const now = Date.now()if (now - lastScanTime.value < 1000) returnlastScanTime.value = now// ✅ 修复:不要写成 if (!isMobile.value); 末尾多分号if (!isMobile.value) {toast('不是手机端登录', 'warning')return}// 避免重复初始化/启动if (isInitializing.value || isScanning.value) {toast('正在打开摄像头…', 'info')return}const container = interactiveRef.value || (document.querySelector('#interactive') | null)if (!container) {toast('找不到扫码容器 #interactive', 'error')return}// 显示并给尺寸(没有尺寸很难识别)container.style.display = 'block'container.style.width = '100%'container.style.height = '60vh'isInitializing.value = truetry {await new Promise((resolve, reject) => {Quagga.init({inputStream: {name: 'Live',type: 'LiveStream',target: container,constraints: {facingMode: 'environment',width: { min: 640 },height: { min: 480 },},},decoder: { readers: ['code_128_reader', 'ean_reader'] },locate: true,},(err) => (err ? reject(err) : resolve()),)})Quagga.start()isScanning.value = truetoast('摄像头已启动', 'success')} catch (e) {console.error('摄像头/初始化失败', e)toast('无法启动摄像头:请使用 HTTPS 并允许相机权限', 'error')stopScan()return} finally {isInitializing.value = false}// 识别一次即关闭(做一次性处理)anyonDetectedHandler = (data) => {if (!isScanning.value) returnconst code = data?.codeResult?.codeif (code) {trackingNumber.value = code // ✅ 把结果写回输入框toast('已识别:' + code, 'success')// todo 在这里添加扫描后需调用的逻辑stopScan()}}Quagga.onDetected(onDetectedHandler)
}// 清理资源
onBeforeUnmount(() => {stopScan()
});</script>

http://www.dtcms.com/a/340763.html

相关文章:

  • RAG系统文本检索优化:Cross-Encoder与Bi-Encoder架构技术对比与选择指南
  • 时序数据库IoTDB的列式存储引擎
  • 5G-A赋能AR眼镜:毫米级虚实融合的未来已来
  • Kubernetes 负载均衡现象解析:为何同一批次请求集中于单个 Pod
  • 小红书账号隔离:解决IP关联问题方案
  • AI 创业公司分析报告:RealRoots
  • 结合SAT-3D,运动+饮食双重养腰新方式
  • 3ds Max 流体模拟终极指南:从创建到渲染,打造真实液体效果
  • MySQL InnoDB事务acid特性的原理和隔离级别的实现原理
  • 机器学习——附录与补充
  • 【007TG洞察】Bitget全球快闪店活动解析:Web3项目如何实现高效用户增长
  • ios八股文 -- Objective-c
  • Java EE ----- Spring Boot 日志
  • 【JavaEE】(17) MyBatis 基础
  • 【JavaEE】多线程(线程安全问题)
  • k8sday12数据存储(1/2)
  • 【表的操作】
  • 开源大模型如何选择?GPT-OSS综合评估
  • HTML--pre标签的作用
  • 决策树1.2
  • Flink学习
  • 数据安全事件分级
  • 嵌入式的各个要点总结(不断更新)
  • Building Systems with the ChatGPT API 使用 ChatGPT API 搭建系统(第二章学习笔记及总结)
  • idea maven 设置代理
  • SSM从入门到实战:2.1 MyBatis框架概述与环境搭建
  • 【STM32】HAL库中的实现(六):DAC (数模转换)
  • 调用海康威视AI开放平台接口实现人体关键点检测
  • Java毕业设计选题推荐 |基于SpringBoot+Vue的知识产权管理系统设计与实现
  • langchain-ds的报告生成提示词