最近公司的業務場景中有個生成二維碼和識別二維碼的需求。生成二維碼以前有作過,選用的 qrcode.js這個前端庫,操做比較簡單。這裏再也不贅述。 剛開始看到二維識別這個需求以爲很簡單,覺得有相應的前端庫直接用就好了。但當真正開始寫功能時,發現二維識別會涉及到不少其餘的功能。廢話再也不多說,仍是來看看如何實現的吧。前端
調用攝像頭web
經過瀏覽器調用攝像頭在h5中已經有個屬性能夠兼容大部分平臺了。 navigator.getUserMedia = navigator.mediaDevices.getUserMedia || navigator.mediaDevices.webkitGetUserMedia || navigator.mediaDevices..mozGetUserMedia;
咱們來看下mdn中的介紹: MediaDevices.getUserMedia()會提示用戶給予使用媒體輸入的許可,媒體輸入會產生一個MediaStream,裏面包含了請求的媒體類型的軌道。此流能夠包含一個視頻軌道(來自硬件或者虛擬視頻源,好比相機、視頻採集設備和屏幕共享服務等等)、一個音頻軌道(一樣來自硬件或虛擬音頻源,好比麥克風、A/D轉換器等等),也多是其它軌道類型。它返回一個 Promise 對象,成功後會resolve回調一個 MediaStream 對象。若用戶拒絕了使用權限,或者須要的媒體源不可用,promise會reject回調一個 PermissionDeniedError 或者 NotFoundError 。查看詳情 也就是說這個屬性的返回值中咱們能夠獲取攝像頭正在拍攝的視頻流動。canvas
獲取視頻流並顯示在video 視頻流經過getUserMedia已經能夠獲取到接下須要把他放到video中:promise
let option = {
width: 1280,
height: 720
}
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({
video: option
}).then(function(stream) {
//將視頻流實時播放在video
self.$refs.video.srcObject = stream
self.$refs.video.style.display = 'block'
//截取video內容
setTimeout(() => {
self.screenShot()
}, 2000);
}).catch(function(err) {
alert(err);
});
} else if (navigator.getUserMedia) {
navigator.getUserMedia({
video: true
}).then(function(stream) {
self.$refs.video.srcObject = stream
self.$refs.video.style.display = 'block'
setTimeout(() => {
self.screenShot()
}, 2000);
}).catch(function(err) {
alert(err);
});
}
複製代碼
當錄像正常顯示時,咱們能夠實時的進行截圖。b瀏覽器
let $canvas = $('canvas');
let $video = $('video');
$canvas.attr({
width: $video.width(),
height: $video.height(),
})
let ctx = $canvas[0].getContext('2d');
ctx.drawImage($video[0], 0, 0, $video.width(), $video.height());
let base64 = $canvas[0].toDataURL('images/png');
//截圖成功對圖片進行識別
this.decodeQrcode(base64)
複製代碼
使用二維碼識別庫reqrcode.js,識別截取的視頻圖片,若是失敗則繼續截圖從新識別bash
decodeQrcode(base64) {
let self = this
// $('#screenshot_img').attr('src', base64)
qrcode.decode(base64)
qrcode.callback = function(imgMsg) {
if (!self.visible) {
return
}
if (imgMsg == 'error decoding QR Code') {
setTimeout(function() {
//截圖從新識別
self.screenShot()
}, 2000)
} else {
alert(imgMsg)
window.location.href = imgMsg
}
}
// }
}
複製代碼
識別成功獲取二維碼內容ide
最後二維碼功能雖然實現了,可是遠遠超過個人預估時間,這裏緣由大部分是由於二維碼識別不單單須要識別二維碼這一功能。在識別前咱們須要實現JavaScript調用攝像頭功能,canvas截圖功能等等一系列問題。因此下次再遇到本身未接觸過的需求,就須要有充分的調研,詳細的分析的需求的難點。ui