haizlin/fe-interview

[软技能] 第155天 你有做过扫码枪的开发吗?知道它的原理吗?

haizhilin2013 opened this issue · 4 comments

第155天 你有做过扫码枪的开发吗?知道它的原理吗?

就记得扫码枪连电脑的时候,鼠标光标在文本中,扫完条码会有一个换行操作

基于微信的 wx.scanQRCode 开发过,就能直接拿到码内的文本了。
拿到文本后是跳转还是另有请求就很业务了。

曾猜想过它的原理,但也不得而知嘛。
首先是打开摄像头,这个 web 端坑很大,甚至苹果机只有 IOS11 的 safari 才刚支持,
所以这是微信 webAPP 与微信之间的 sdk 沟通了。
然后是扫码,我猜是拍照然后解析哈,代码上可能是个递归,定时拍照我觉得不太必要。
解析二维码方面没啥研究,应该是某个第三方吧。

当时做的时候用的是移动提供的硬件设备,底层定义好了对应的API,直接使用就可以了;当时的场景需要注意的是连续扫描的时候,前一个扫描结果未处理完的时候需要阻塞下一步扫描,这里就涉及到同步异步的问题了

扫码枪是一种类似键盘的输入设备,扫码完成后会以极快的速度输入扫描到的字符,一般在末尾会带一个换行符。原理是检测 keydown 事件两次输入的间隔如果小于一个值的话就当成扫码枪输入。

barcodeScanner.js

/**
 * 检测扫码枪输入
 * 创建实例:let bsd = new BarcodeScannerDetect(cb)
 * 开始检测:bsd.startDetect()
 * 关闭检测:bsd.stopDetect()
 * 参考:https://www.jianshu.com/p/3019858e3cad
 * @param callback 扫码枪输入结束回调
 * @constructor
 */
function BarcodeScannerDetect(callback) {
  this.lastTime = null
  this.nextTime = null
  this.code = ''

  this.detect = (e) => {
    const keycode = e.keyCode || e.which || e.charCode
    this.nextTime = new Date()
    // 回车键13
    if (keycode === 13) {
      if (this.lastTime && this.nextTime - this.lastTime < 30) {
        // 扫码枪
        // console.log(this.code)
        callback(this.code)
      } else {
        // 键盘
      }
      this.code = ''
      this.lastTime = null
      e.preventDefault()
    } else {
      // 忽略一些没用的字符以及中文输入法bug字符
      if (keycode !== 16 && keycode !== 229) {
        if (!this.lastTime) {
          this.code = String.fromCharCode(keycode)
        } else {
          if (this.nextTime - this.lastTime < 30) {
            // console.log(keycode, String.fromCharCode(keycode))
            this.code += String.fromCharCode(keycode)
          } else {
            this.code = ''
          }
        }
      }
      this.lastTime = this.nextTime
    }
  }
}

BarcodeScannerDetect.prototype.startDetect = function() {
  // console.log('startDetect')
  document.addEventListener('keydown', this.detect)
}

BarcodeScannerDetect.prototype.stopDetect = function() {
  // console.log('stopDetect')
  document.removeEventListener('keydown', this.detect)
}

export default BarcodeScannerDetect