web实现usb扫码枪读取二维码数据功能

打印 上一主题 下一主题

主题 836|帖子 836|积分 2508


前言

   常见的扫码枪有2种,一种串口扫码枪通过串口实现数据通信,技能实现上使用Web Serial API,可以查看本人另一篇博文Web Serial API串口通信,实现web和electron扫码枪读取数据。另一种是usb扫码枪,也是本文所要报告的,usb扫码枪可以当作是输入设备,实际等同于键盘通过按键输入方式举行二维码信息读取,技能实现相比串口扫码枪简单多了,只需监听输入事件,但是它也有许多弊端和限制。
  
一、usb扫码枪获取数据步调和条件

1.必须有个input输入框而且让其处于聚焦状态
2.监听输入框按键事件keydown大概keyup,碰到keyCode为13(回车)表现输入结束(一样平常usb扫码枪设置读取以回车结束,固然有的也可以设置其他,如果是其他结束符就监听相应的keyCode)
3.回车结束后从input输入框dom对象获取value值就是二维码内容
通过上面总结很容易实现,如下代码:
  1. <input id="input"/>   
复制代码
  1.   <script>
  2.    const input= document.getElementById('input');
  3.    input.addEventListener('keydown',e=>{
  4.      if(e.keyCode==13){//回车结束
  5.         let qrcodeData=input.value;
  6.         console.log(`二维码数据为${qrcodeData}`)
  7.      }
  8.    })
  9.    input.focus()//聚焦
  10.   </script>
复制代码
扫码测试:

二、优化

上面demo我们只是简单实现了从扫码枪获取数据功能的核心逻辑,但实际开发中我们的需求场景大概不一样,会碰到许多问题和坑点需要优化办理。
   挖坑1:中文输入法会影响输入内容精确性,可以通过设置input type=“password”,设置输入框为密码类型办理
    挖坑2:如果你的需求是读取二维码内容添补到一个特定输入框可以像上面例子一样实现,但是如果读取二维码不需要添补到输入框大概需要回显许多个地方就需要先获取数据再做数据处置处罚,这个时间可以谋利取巧画个输入框移动到屏幕外。
    挖坑3:当你采用挖坑2技巧把输入框画在屏幕外,并用代码聚焦在输入框后,用户大概乱点页面导致读取数据前失焦,从而无法正常读取到二维码数据。办理方法可以定时不间断自动对焦并显示加载模态框引导用户不去乱点击,淘汰失败率。
  二、代码实现

   接下来将以vue3 elementui-plus来举例,实现一个扫码获取多个表单字段回显功能
  操作逻辑设计:
1.页面设计一个二维码辨认按钮
2.用户点击按钮触发扫码功能并锁定界面出现辨认中加载转圈,防止用户乱点击失焦。
3.扫码辨认,辨认成功,辨认加载转圈消失,数据自动回显到对应表单控件上
4.n秒内如果用户未扫码关闭加载转圈恢复初态
代码如下(示例):
scanner.js(扫码逻辑封装hook):
  1. import { nextTick, onMounted } from "vue";
  2. import { ElLoading, ElMessage } from "element-plus";
  3. let isInputing = false; //是否在输入中
  4. /**
  5. *
  6. * @param {*} inputRef:输入框Ref
  7. * @param {*} callBack :识别回调
  8. * @returns
  9. */
  10. const useScancer = (inputRef, callBack) => {
  11.   let interval = null; //定时器实例
  12.   let loading = null; //ElLoading组件实例
  13.   //输入框绑定keydown事件
  14.   const addKeydownEvent = () => {
  15.     if (inputRef?.value) {
  16.       inputRef.value.addEventListener("keydown", (event) => {
  17.         isInputing = true;
  18.         let keyCode = event.keyCode || event.which;
  19.         if (keyCode === 13) {
  20.           let qrcodeData = inputRef?.value?.value ?? ""; //二维码数据
  21.           if (interval) {
  22.             clearInterval(interval);
  23.             interval = null;
  24.           }
  25.           callBack(qrcodeData);
  26.           inputRef.value.value = "";
  27.           loading && loading.close();
  28.           loading = null;
  29.           ElMessage.success("识别成功");
  30.           isInputing = false;
  31.         }
  32.       });
  33.     }
  34.   };
  35.   //自动聚焦
  36.   const autoFocus = () => {
  37.     //立即执行
  38.     inputFocus();
  39.     if (!interval) {
  40.     //每50ms自动对焦
  41.       interval = setInterval(() => {
  42.         inputFocus();
  43.       }, 50);
  44.     }
  45.   };
  46.   //input聚焦
  47.   const inputFocus = () => {
  48.     if (inputRef && inputRef.value) {
  49.       inputRef.value.focus();
  50.     }
  51.   };
  52.   //开始扫码
  53.   const handleScanCode = () => {
  54.     if (!loading) {
  55.       console.log('loading')
  56.       loading = ElLoading.service({
  57.         lock: true,
  58.         text: "请开始扫码识别",
  59.         background: "rgba(255, 255, 255, 0.7)",
  60.       });
  61.       //20秒内未扫码关闭loading
  62.       setTimeout(() => {
  63.         if (!isInputing) {
  64.           loading && loading.close();
  65.           loading = null;
  66.           if (interval) {
  67.             clearInterval(interval);
  68.             interval = null;
  69.           }
  70.         }
  71.       }, 20 * 1000);
  72.       nextTick(() => {
  73.         autoFocus();
  74.       });
  75.     }
  76.   };
  77.   //初始化绑定事件
  78.   onMounted(() => {
  79.     addKeydownEvent();
  80.   });
  81.   return { autoFocus, handleScanCode };
  82. };
  83. export default useScancer;
复制代码
页面调用
index.vue
  1. <template>
  2.   <input class="input" ref="inputRef" type="password"/>
  3.   <el-button @click.native="handleScanCode" type="primary">扫码识别</el-button>
  4.   <el-form :model="formData" style="margin-top: 20px">
  5.     <el-form-item label="姓名">
  6.       <el-input disabled v-model="formData.name" />
  7.     </el-form-item>
  8.     <el-form-item label="年龄">
  9.       <el-input disabled v-model="formData.age" />
  10.     </el-form-item>
  11.     <el-form-item label="生日">
  12.       <el-input disabled v-model="formData.birthday" />
  13.     </el-form-item>
  14.   </el-form>
  15. </template>
  16. <script setup>
  17. import { ref, reactive } from "vue";
  18. import useScancer from "./scanner.js"; //扫码识别hook
  19. //表单数据
  20. const formData = reactive({
  21.   name: "",
  22.   age: "",
  23.   birthday: "",
  24. });
  25. //输入框
  26. const inputRef = ref();
  27. //扫码回调
  28. const { handleScanCode } = useScancer(inputRef, (data) => {
  29.   console.log(data, "二维码数据为:data");
  30.   if (data) {
  31.     try {
  32.     //二维码字符串转为json对象
  33.       data= JSON.parse(data);
  34.       for(let key in formData){
  35.         formData[key]=data[key]??'';
  36.       }
  37.     } catch (e) {
  38.       console.log(e,'e')
  39.     }
  40.   }
  41. });
  42. </script>
  43. <style scoped>
  44. .input {
  45.   position: fixed;
  46.   left: 0;
  47.   transform: translateX(-200%);
  48. }
  49. </style>
复制代码
测试运行:
初始态:

开始辨认:

辨认完成:


总结

通过上面介绍可以看出usb扫码枪固然使用简单,但是限制多,只能满意一些特定场景,对用户一些不确定操作大概会影响读取成功率,这个时间也可以从产物设计上引导用户自动触发聚焦淘汰用户乱点击频率,提高成功率。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

雁过留声

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表