html5調(diào)用設(shè)備攝像頭刃滓,實(shí)現(xiàn)二維碼掃描

最近在做一個(gè)簽到系統(tǒng),由于我直接使用了純網(wǎng)頁卓缰,因此調(diào)用攝像頭進(jìn)行掃碼成了大問題砰诵。經(jīng)過幾番費(fèi)力的百度終于找到解決方法。

主要用到MediaDevices.getUserMedia()這個(gè)方法鳍鸵。(僅支持https)

  • 創(chuàng)建一個(gè)QRScan對象
    function QRScan(div_id) {
        this.div_id = div_id;  // 用來存放video的div id
        this.div_can = null; 
        this.videos = [];      // 保存設(shè)備上所有的攝像頭id
        this.medioConfig = {};  // 配置
        this.can_open = false;
        this.init();
    }

在web api上調(diào)用后置攝像頭是這樣配置video: { facingMode: { exact: "environment" } }尉间,但是我沒有成功击罪,我是通過獲取所有設(shè)備id然后再指定使用id的方式實(shí)現(xiàn)(英語差的我費(fèi)勁的看了半天文檔才弄明白)媳禁。

  • 初始化配置等
        init: function () {
            // 各種兼容
            win.URL = (win.URL || win.webkitURL || win.mozURL || win.msURL);
            var promisifiedOldGUM = function(constraints) {
                var getUserMedia = (navigator.getUserMedia ||
                    navigator.webkitGetUserMedia || navigator.mozGetUserMedia);
                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(navigator.mediaDevices === undefined) {
                navigator.mediaDevices = {};
            }
            if(navigator.mediaDevices.getUserMedia === undefined) {
                navigator.mediaDevices.getUserMedia = promisifiedOldGUM;
            }

            var self = this;
            self.div_can = doc.getElementById(self.div_id);
            // 這里獲取所有的攝像頭設(shè)備id
            navigator.mediaDevices.enumerateDevices().then(function(devices) {
                devices.forEach(function (dv) {
                    var kind = dv.kind;
                    if (kind.match(/^video.*/)) {
                        self.videos.push(dv.deviceId);
                        console.log(dv);
                    }
                });
                var len = self.videos.length;
                self.can_open = true;
                // 默認(rèn)使用后置攝像頭竣稽。根據(jù)測試毫别,在手機(jī)上后置攝像頭的id會在之后獲取
                self.medioConfig = {
                    audio: false,
                    video: { deviceId: self.videos[len - 1] }
                }
            });
        }
  • 打開攝像頭部分
      openScan: function () {
            var self = this;
            if (self.can_open) {
                var vd = doc.createElement('video');
                vd.setAttribute('id', 'video_id');
                navigator.mediaDevices.getUserMedia(self.medioConfig).then(function (stream) {
                    vd.src = win.URL.createObjectURL(stream);
                    self.div_can.appendChild(vd);
                }).catch(function (err) {
                    var p = doc.createElement('p');
                    p.innerHTML = 'ERROR: ' + err.name +
                                  '<br>該瀏覽器不支持調(diào)用攝像頭典格,請使用**瀏覽器';
                    self.div_can.appendChild(p);
                });
                vd.play();
            }
        }

到這里我們就能成功打開設(shè)備攝像頭了,當(dāng)然這是需要瀏覽器支持的

  • 在video中進(jìn)行圖像抓取
        getImgDecode: function (func) {
            var self = this;
            var video = doc.getElementById('video_id');
            var canvas = doc.createElement('canvas');
            canvas.width = 340;
            canvas.height = 305;
            var ctx = canvas.getContext('2d');
            ctx.drawImage(video, 0, 0, 340, 305);
            if (canvas.toBlob === undefined) {
                var base64 = canvas.toDataURL();
                var blob = self.Base64ToBlob(base64);
                self.sendBlob(blob, func);
            } else {
                canvas.toBlob(function (blob) {
                    self.sendBlob(blob, func);
                });
            }
        },

        Base64ToBlob: function (base64) {
            var code = win.atob(base64.split(',')[1]);
            var len = code.length;
            var as = new Uint8Array(len);
            for (var i = 0; i < len; i++) {
                as[i] = code.charCodeAt(i);
            }
            return new Blob([as], {type: 'image/png'});
        }
  • 將獲取的二進(jìn)制文件上傳
        sendBlob: function (blob, func) {
            var fd = new FormData();
            fd.append('file', blob);
            var xhr = new XMLHttpRequest();
            xhr.open('post', 'http://ip/api/parse', true);
            xhr.onload = function () {
               func ? func(JSON.parse(xhr.responseText)) : null;
            };
            xhr.send(fd);
        }

我這里自己實(shí)現(xiàn)了個(gè)二維碼解碼接口,直接使用就能實(shí)現(xiàn)二維碼讀取防嗡。返回解碼結(jié)果,這樣的接口百度一下就有很多疫衩。

源碼地址:github-qrscan荣德,實(shí)例: qrscan

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涮瞻,一起剝皮案震驚了整個(gè)濱河市假褪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌生音,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慕匠,死亡現(xiàn)場離奇詭異台谊,居然都是意外死亡蓉媳,警方通過查閱死者的電腦和手機(jī)酪呻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門玩荠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人阶冈,你說我怎么就攤上這事立帖。” “怎么了堂飞?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵绑咱,是天一觀的道長。 經(jīng)常有香客問我铝噩,道長窿克,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任具被,我火速辦了婚禮只损,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘跃惫。我一直安慰自己,他們只是感情好蛉顽,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布蜂林。 她就那樣靜靜地躺著遥诉,像睡著了一般矮锈。 火紅的嫁衣襯著肌膚如雪睁蕾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天瀑凝,我揣著相機(jī)與錄音臭杰,去河邊找鬼。 笑死渴杆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的囊拜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼冠跷,長吁一口氣:“原來是場噩夢啊……” “哼蜜托!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起橄务,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎柑司,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體攒驰,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡玻粪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年诬垂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了结窘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片充蓝。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖官脓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卑笨,我是刑警寧澤仑撞,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站搀缠,受9級特大地震影響近迁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鉴竭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瑰步。 院中可真熱鬧璧眠,春花似錦、人聲如沸责静。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腰鬼。三九已至塑荒,卻和暖如春姜挺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背初家。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工溜在, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掖肋。 一個(gè)月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像沿盅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子腰涧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,522評論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫窖铡、插件坊谁、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,033評論 4 62
  • 一眨眼就在這座城市呆了七年。以前總覺得那種張口閉口就說在某座城市呆了十幾二十年的人需要很用力堅(jiān)持口芍,所以臉上才...
    秋遲_b463閱讀 236評論 0 0
  • 你是真的想娶我鬓椭,你媽媽已經(jīng)開始催著要吃訂婚飯要我們先把證領(lǐng)了然后想什么時(shí)候辦事再辦,你家人都希望快點(diǎn)結(jié)婚小染,各種著急...
    marshallmathers閱讀 213評論 0 0
  • 做事情有計(jì)劃可以帶給孩子自信和成就感,當(dāng)孩子看到面前成堆的學(xué)習(xí)任務(wù)被狠狠地劃去春畔,象征著這些敵人被征服和消滅脱货,那就像...
    好習(xí)慣2011閱讀 239評論 0 0