点我去Gitee
点我去Gitee

扫描二维码 mediaDevices.getUserMedia+jsqr方法

扫描二维码 mediaDevices.getUserMedia+jsqr方法

前言

之前想做移动端的到吗功能 然会就找到这个方法,但是这种方法限制比较多。首先需要https协议,其次我只会在wap和web端运行,在app端我运行不出来(可能是可以的,只是我不会而已)。
其中,【mediaDevices.getUserMedia】是用于吊起手机摄像头的方法。【jsqr】是用于扫面二维码的一个npm包。

实现思路

通过mediaDevices.getUserMedia方法调起录像功能,把视频赋给video,在截取视频中的某一帧传给jsqr进行解析,如果解析出二维码则返回解析数据,没有的话就继续截取

注意事项

调起摄像头必须在https的协议下,否则会不起作用。

一、mediaDevices.getUserMedia

官网用法:(兼容老的浏览器)

// 1.写调用设想头的参数
// 想要获取一个最接近 1280x720 的相机分辨率
// var constraints = { audio: true, video: { width: 1280, height: 720 } };
// 强制使用后置摄像头
var constraints = { audio: true, video: { facingMode: { exact: "environment" } } }

// 2.进行老的浏览器的兼容
// 老的浏览器可能根本没有实现 mediaDevices,所以我们可以先设置一个空的对象
if (navigator.mediaDevices === undefined) {
  navigator.mediaDevices = {};
}
// 一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia
// 因为这样可能会覆盖已有的属性。这里我们只会在没有getUserMedia属性的时候添加它。
if (navigator.mediaDevices.getUserMedia === undefined) {
  navigator.mediaDevices.getUserMedia = function(constraintss) {
    // 首先,如果有getUserMedia的话,就获得它
    var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
    // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
    if (!getUserMedia) {
      return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
    }
    // 否则,为老的navigator.getUserMedia方法包裹一个Promise
    return new Promise(function(resolve, reject) {
      getUserMedia.call(navigator, constraintss, resolve, reject);
    });
  }
}

// 3.开始使用方法  进行启用摄像头
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
  var video = document.querySelector('video');
  // 旧的浏览器可能没有srcObject
  if ("srcObject" in video) {
    video.srcObject = stream;
  } else {
    // 防止在新的浏览器里使用它,应为它已经不再支持了
    video.src = window.URL.createObjectURL(stream);
  }
  video.onloadedmetadata = function(e) {
    video.play();
  };
})
.catch(function(err) {
  console.log(err.name + ": " + err.message);
});

权限

在一个可安装的app(如Firefox OS app)中使用 getUserMedia() ,你需要在声明文件中指定以下的权限:

"permissions": {
  "audio-capture": {
    "description": "Required to capture audio using getUserMedia()"
  },
  "video-capture": {
    "description": "Required to capture video using getUserMedia()"
  }
}

二、jsqr

const code = jsQR(imageData,width,height,options ?);
if(code){
 console.log(“找到二维码”,code);
}

三、结合用法

代码原文链接:https://blog.csdn.net/weixin_43827462/article/details/119350721

import React, { PureComponent } from 'react';
import '../index.less';
import jsQR from 'jsqr';

let scanner = null;

let video = null;
let canvasElement = null;
let canvas = null;
let loadingMessage = null;
let outputContainer = null;
let outputMessage = null;
let outputData = null;

export default class scanPage extends PureComponent {
  componentDidMount() {
    const that = this;
    video = document.createElement('video');
    canvasElement = document.getElementById('canvas');
    canvas = canvasElement.getContext('2d');
    loadingMessage = document.getElementById('loadingMessage');
    outputContainer = document.getElementById('output');
    outputMessage = document.getElementById('outputMessage');
    outputData = document.getElementById('outputData');

    console.log(navigator.mediaDevices )

    // 老的浏览器可能根本没有实现 mediaDevices,所以我们可以先设置一个空的对象
    if (navigator.mediaDevices === undefined) {
      navigator.mediaDevices = {};
    }

    // 一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia
    // 因为这样可能会覆盖已有的属性。这里我们只会在没有getUserMedia属性的时候添加它。
    if (navigator.mediaDevices.getUserMedia === undefined) {
      navigator.mediaDevices.getUserMedia = function (constraints) {
        // 首先,如果有getUserMedia的话,就获得它
        var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

        // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
        if (!getUserMedia) {
          return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
        }

        // 否则,为老的navigator.getUserMedia方法包裹一个Promise
        return new Promise(function (resolve, reject) {
          getUserMedia.call(navigator, constraints, resolve, reject);
        });
      };
    }

    navigator.mediaDevices
      .getUserMedia({ audio: false, video: { facingMode: "environment" } })
      .then(function (stream) {
        // 旧的浏览器可能没有srcObject
        video.srcObject = stream;
        video.setAttribute('playsinline', true); // required to tell iOS safari we don't want fullscreen
        video.play();
        window.requestAnimationFrame(that.tick);
      })
      .catch(function (err) {
        console.log(err.name + ': ' + err.message);
      });
  }

  handleStartCode = () => {
    scanner.start();
  };

  componentWillUnmount() {}

  drawLine = (begin, end, color) => {
    canvas.beginPath();
    canvas.moveTo(begin.x, begin.y);
    canvas.lineTo(end.x, end.y);
    canvas.lineWidth = 4;
    canvas.strokeStyle = color;
    canvas.stroke();
  };

  tick = () => {
    loadingMessage.innerText = '⌛ Loading video...';
    if (video.readyState === video.HAVE_ENOUGH_DATA) {
      loadingMessage.hidden = true;
      canvasElement.hidden = false;
      outputContainer.hidden = false;

      canvasElement.height = video.videoHeight;
      canvasElement.width = video.videoWidth;
      canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
      var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
      var code = jsQR(imageData.data, imageData.width, imageData.height, {
        inversionAttempts: 'dontInvert',
      });
      if (code && code.data) {
        console.log(code);
        this.drawLine(code.location.topLeftCorner, code.location.topRightCorner, '#FF3B58');
        this.drawLine(code.location.topRightCorner, code.location.bottomRightCorner, '#FF3B58');
        this.drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, '#FF3B58');
        this.drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, '#FF3B58');
        outputMessage.hidden = true;
        outputData.parentElement.hidden = false;
        outputData.innerText = code.data;
        //this.props.history.replace(
        //  `/client-mng/individual-business-mng/list/detail/${code.data}-selfEERegister-scan`
        //);
      } else {
        outputMessage.hidden = false;
        outputData.parentElement.hidden = true;
      }
    }
    window.requestAnimationFrame(this.tick);
  };

  render() {
    return (
      <div>
        <div id="loadingMessage">
          🎥 Unable to access video stream (please make sure you have a webcam enabled)
        </div>
        <canvas id="canvas" hidden></canvas>
        <div id="output" hidden>
          <div id="outputMessage">No QR code detected.</div>
          <div hidden>
            <b>Data:</b> <span id="outputData"></span>
          </div>
        </div>
      </div>
    );
  }
}
posted @ 2021-09-19 14:16  biuo  阅读(734)  评论(0编辑  收藏  举报