扫描二维码 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>
);
}
}