最近在做一個(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