純web端實現二維碼識別

前言

最近公司的業務場景中有個生成二維碼和識別二維碼的需求。生成二維碼之前有做過,選用的 qrcode.js這個前端庫,操作比較簡單。這裏不再贅述。
剛開始看到二維識別這個需求覺得很簡單,以爲有相應的前端庫直接用就行了。但當真正開始寫功能時,發現二維識別會涉及到很多其他的功能。廢話不再多說,還是來看看如何實現的吧。

實現流程

  • 調用攝像頭

    通過瀏覽器調用攝像頭在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 。查看詳情
    也就是說這個屬性的返回值中我們可以獲取攝像頭正在拍攝的視頻流動。

  • 獲取視頻流並顯示在video
    視頻流通過getUserMedia已經可以獲取到接下需要把他放到video中:

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);
                    });
                }
  • canvas實現截圖

當錄像正常顯示時,我們可以實時的進行截圖。b

                let $canvas = $('canvas');
                let $video = $('video');
                let test = $('#source');
                $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,識別截取的視頻圖片,如果失敗則繼續截圖重新識別


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
                    }
                }
                // }
            }
  • 獲取識別內容

識別成功獲取二維碼內容

總結

最後二維碼功能雖然實現了,但是遠遠超過我的預估時間,這裏原因大部分是因爲二維碼識別不僅僅需要識別二維碼這一功能。在識別前我們需要實現JavaScript調用攝像頭功能,canvas截圖功能等等一系列問題。所以下次再遇到自己未接觸過的需求,就需要有充分的調研,詳細的分析的需求的難點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章