在h5页面中调用摄像头实现扫描二维码功能
生产环境必须是https
<div id="app">
<div class="scannow" @click="openScan">扫一扫</div>
<div class="scanMask" v-show="showMask">
<div class="scanvideo" v-show="showVideo">
<video
id="videoEle"
ref="videoEle"
width="300"
height="300"
playsinline
autoplay
x5-video-player-type="h5"
style='object-fit:fill'
></video>
</div>
<div class="scancanvas" v-show="!showVideo">
<canvas width="300" height="300" id="canvasEle" ref="canvasElement"></canvas>
</div>
</div>
</div>
import jsQR from 'jsqr'
data(){
return{
canvas2d: undefined,
outputData:null,
showVideo: true,
showMask: false,
}
},
destroyed (){
this.closeCamera()
},
主要方法:
methods:{
//调摄像头
openScan(){
this.showMask = true
//Toast("摄像头启动中...")
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function (constraints) {
var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
if (!getUserMedia) {
return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
}
return new Promise(function (resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
}
}
if (window.stream) {
window.stream.getTracks().forEach(track => {
track.stop();
});
}
var constraints = window.constraints = {
audio: false,
video: {
sourceId: 'default',
facingMode: { exact: "environment" }
}
};
navigator.mediaDevices.getUserMedia(constraints).then(stream=>{
var video = document.getElementById('videoEle');
// 旧的浏览器可能没有srcObject
if ("srcObject" in video) {
video.srcObject = stream;
} else {
// 防止在新的浏览器里使用它,应为它已经不再支持了
video.src = window.URL.createObjectURL(stream);
}
video.onloadedmetadata = function() {
video.play();
};
requestAnimationFrame(this.tick)
}).catch(err=>{
console.log(err)
//Toast(err)
})
},
tick(){
if( this.$refs.videoEle.readyState === this.$refs.videoEle.HAVE_ENOUGH_DATA ) {
//this.canvasHeight = this.$refs.videoEle.videoHeight
//this.canvasWidth = this.$refs.videoEle.videoWidth
!this.canvas2d && (this.canvas2d = this.$refs.canvasElement.getContext('2d'))
this.canvas2d.drawImage(this.$refs.videoEle, 0, 0, 300, 300)
var imageData = this.canvas2d.getImageData(0, 0, 300, 300)
var code = jsQR(imageData.data, imageData.width, imageData.height, {
inversionAttempts: 'dontInvert'
})
if (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')
this.outputData = code.data
this.closeCamera()
return false
} else {
this.outputData = null
}
}
requestAnimationFrame(this.tick)
},
//绘制canvas
drawLine (begin, end, color) {
this.canvas2d.beginPath()
this.canvas2d.moveTo(begin.x, begin.y)
this.canvas2d.lineTo(end.x, end.y)
this.canvas2d.lineWidth = 4
this.canvas2d.strokeStyle = color
this.canvas2d.stroke()
},
closeCamera(){
this.showVideo=false
if (this.$refs.videoEle.srcObject) {
this.$refs.videoEle.srcObject.getTracks().forEach(function (track) {
track.stop()
})
this.$refs['videoEle'].srcObject = null
}
//this.showMask = false
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。