前端调用手机摄像头权限进行扫码解析(demo含Vue及原生js写法)

项目必须基于HTTPS协议!!!

引子

本人马上毕业了,现在在新单位实习前端,有个需求需要在移动Web端调用摄像头进行扫码,这方面之前没有接触过,但时间有限,只能走一步看一步,首先收集资料:

  1. 调用设备扫码功能在安卓app上有api可以调用,Hbulider 5+app中也有现成的api,但我这个项目已经开发了很久了,只能新加模块,显然不符合上面的情况。
  2. 原生Web有个api叫 Navigator.mediaDevices。
    mediaDevices 是 Navigator 只读属性,返回一个 MediaDevices 对象,该对象可提供对相机和麦克风等媒体输入设备的连接访问,也包括屏幕共享。
  3. 扫码解析则可以使用 qrcode.js 这一个js库。

实践

// 调用摄像头方法,原生Navigator.mediaDevices api
function setwebcam(){
var options = true;
if(navigator.mediaDevices && navigator.mediaDevices.enumerateDevices)
{
  try{
      navigator.mediaDevices.enumerateDevices().then(function(devices) {
        devices.forEach(function(device) {
          if (device.kind === 'videoinput') {
		options={'deviceId': {'exact':device.deviceId}, 'facingMode':'environment'} ;
			console.log(device);
            }
           console.log(device.kind + ": " + device.label +" id = " + device.deviceId);
          });
		  console.log(options)
          setwebcam2(options);
        });
    }
    catch(e)
    {
        console.log(e);
    }
}
else{
    console.log("无设备信息。" );
}
}

其中 ‘facingMode’:‘environment’ 则可以稳定调用后置摄像头,不会再出现网上大家所说的调用前置的情况。
此时需要与前端元素配合

// html 样式自调
<div class="container">
        <div id="scan">
            <video id="vcode" autoplay></video>
            <canvas id="code-canvas"></canvas>
        </div>
    </div>
start()
//  function
function start(){
    createCanvas(800,600);
    setwebcam();
}
// 此处借鉴了导师给的方法,构建canvas
function createCanvas(w,h){
    n = navigator;
    v = document.getElementById("vcode");
    var gCanvas = document.getElementById("code-canvas");
    gCanvas.style.width = w + "px";
    gCanvas.style.height = h + "px";
    gCanvas.width = w;
    gCanvas.height = h;
    gCtx = gCanvas.getContext("2d");
    gCtx.clearRect(0, 0, w, h);
	console.log("canvas complete!");
} 
function setwebcamres(options){
          var setvideo = n.mediaDevices.getUserMedia({video: options, audio: false});
          setvideo.then(success, error);

}

此时已经可以成功调用摄像头,接下来集成进Vue工程中

安装zxing.js依赖

npm i @zxing/library --save
npm install --save webrtc-adapter

<template>
  <div class="container">
    <video
      id="video"
      ref="video"
      width="421"
      height="400"
      class="video-container"
    ></video>
      <div>{{ textContent }}</div>
  </div>
</template>

<script>
  import adapter from 'webrtc-adapter';
  // WebRTC适配器 只需要引入
  import { BrowserMultiFormatReader } from '@zxing/library';
  export default {
    data() {
      return {
        codeReader: new BrowserMultiFormatReader(),
        textContent: undefined,
      };
    },
    async created() {
      this.codeReader.getVideoInputDevices()
        .then((videoInputDevices) => {
          const selectedDeviceId = videoInputDevices[1].deviceId; //第二个摄像头
          this.codeReader.decodeFromInputVideoDeviceContinuously(selectedDeviceId, 'video', (result, err) => {
            if (result) {
              console.log(result);
              this.textContent = result.text;
              this.scanRoomResult(this.textContent);
            }
            if (err && !(err)) {
              console.error(err);
            }
          });
          console.log(`Started continous decode from camera with id ${selectedDeviceId}`);
        })
        .catch((err) => {
          console.error(err);
        });
    },
    methods: {
      scanRoomResult(roomName) {
        this.scanRoomInfo = roomName;
        this.scanRoomInfo = JSON.parse(this.scanRoomInfo);// 将字符串转换成json对象
        if (!this.scanRoomInfo.locationId) {
          this.textContent = 'QrCode Error!';
            } else {
          this.textContent = this.scanRoomInfo.locationId;
          const selector = this.$refs['inspectionRuleSelector'];
          selector && (selector.showRulePicker = true);
        }
      }
    }
  };
</script>

<style scoped lang="less">
.container{
  position: relative;
}
  .video-container{
    margin-top: 5vh;
  }
</style>

最后

以上,在Vue中使用zxing有一点不好就是摄像头可控性不强,他的源码构造函数中没有把facingMode放出来,这也就不太好控制摄像头顺序,因为每个手机摄像头顺序都不一定是相同的。
字段中没有判断摄像头的字段

Logo

前往低代码交流专区

更多推荐