在app項目中實現HTML5的掃描二維碼,網上的搜了一大推,但是實際使用的時候發現能直接上手的並不多,所以自己百度,然後提煉了一些,下面直接上代碼。
在線示例
注意:
1.安卓(5.1)有些手機中測試正常,iOS暫時不行,後續再研究。
2.需要自己打包成APP,比如用Hbuilder打包,因爲攝像頭涉及權限問題。(我打包的下載)
js插件鏈接:
http://www.jq22.com/demo/jQueryQrcode201709202327/analyticCode.js
http://www.jq22.com/demo/jQueryQrcode201709202327/llqrcode.js
<!DOCTYPE html>
<head>
<title>HTML5 GetUserMedia Demo</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<style>
body {
text-align: center;
margin: 0;
}
.hide {
display: none;
}
.toast {
position: fixed;
bottom: 150px;
left: 50%;
background: rgba(35,35,35,0.8);
color: #fff;
padding: 5px 15px;
transform: translate(-50%, 50%);
border-radius: 5px;
}
video {
width: 100vw;
}
</style>
</head>
<body>
<video autoplay="autoplay"></video>
<canvas id="canvas1" height="320px" class="hide"></canvas>
<img class="hide" src="" alt="" id="img" />
<div></div>
<span class="toast hide" id="toast">
</span>
<button id="scan">掃一掃</button>
<script src="http://www.jq22.com/demo/jQueryQrcode201709202327/analyticCode.js" type="text/javascript" charset="utf-8"></script>
<script src="http://www.jq22.com/demo/jQueryQrcode201709202327/llqrcode.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
var video = document.querySelector('video');
var audio, audioType;
var canvas1 = document.getElementById('canvas1');
var context1 = canvas1.getContext('2d');
var stream;
// 兼容不同瀏覽器內核
// 老的瀏覽器可能根本沒有實現 mediaDevices,所以我們可以先設置一個空的對象
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
// 一些瀏覽器部分支持 mediaDevices。我們不能直接給對象設置 getUserMedia
// 因爲這樣可能會覆蓋已有的屬性。這裏我們只會在沒有getUserMedia屬性的時候添加它。
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function(constraints) {
// 首先,如果有getUserMedia的話,就獲得它
var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// 一些瀏覽器根本沒實現它 - 那麼就返回一個error到promise的reject來保持一個統一的接口
if (!getUserMedia) {
return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
}
// 否則,爲老的navigator.getUserMedia方法包裹一個Promise
return new Promise(function(resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
}
}
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
var exArray = [];
navigator.mediaDevices.enumerateDevices()
.then(function(sourceInfos) {
for (var i = 0; i != sourceInfos.length; ++i) {
var sourceInfo = sourceInfos[i];
//這裏會遍歷audio,video,所以要加以區分
if (sourceInfo.kind === 'video') {
exArray.push(sourceInfo.deviceId);
}
}
})
.catch(function(err) {
alert(err.name + ": " + err.message);
});
function getMedia() {
if (navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({
audio: false,
video: {
facingMode: { exact: "environment" }
}
}).then(function(stream) {
successFunc(stream)
})
.catch(function(err) {
errorFunc(err)
});
}
else {
alert('Native device media streaming (getUserMedia) not supported in this browser.');
}
}
// 初始就加載攝像頭,不加定時會出現顯示的前置攝像頭(大概因爲打開攝像頭也要時間)
/*setTimeout(function() {
getMedia();
}, 500);*/
function successFunc(stream) {
//alert('Succeed to get media!');
if (video.mozSrcObject !== undefined) {
//Firefox中,video.mozSrcObject最初爲null,而不是未定義的,我們可以靠這個來檢測Firefox的支持
video.mozSrcObject = stream;
}
else {
video.src = window.URL && window.URL.createObjectURL(stream) || stream;
}
}
function errorFunc(e) {
alert('Error!'+e);
}
var getImgTiming = null;
// 將視頻幀繪製到Canvas對象上,Canvas每60ms切換幀,形成肉眼視頻效果
function drawVideoAtCanvas(video,context) {
window.setInterval(function () {
context.drawImage(video, 0, 0,240,320);
}, 3000);
// 定時進行圖片轉換成二維碼
getImgTiming = window.setInterval(function () {
getImg();
}, 1000);
}
// vedio播放時觸發,繪製vedio幀圖像到canvas
video.addEventListener('play', function () {
drawVideoAtCanvas(video, context1);
}, false);
// 轉化圖片
function getImg() {
var dataURL = canvas1.toDataURL("image/png");
// 加載文件
document.getElementById('img').src = dataURL;
getUrl(document.getElementById('img'), 'img-url');
}
// 獲取二維碼地址
function getUrl(e,param){
analyticCode.getUrl(param,e,function(text,imgSrc){
// 判斷是否解析成功
if (text == 'error decoding QR Code') {
document.getElementById('toast').innerHTML = '請對準二維碼';
document.getElementById('toast').classList.remove('hide');
} else {
document.getElementById('toast').innerHTML = '識別成功';
document.getElementById('toast').classList.remove('hide');
// 如果成功,請求接口、取消定時解析圖片
setTimeout(function () {
document.getElementById('toast').classList.add('hide');
clearInterval(getImgTiming);
}, 3000);
e.nextElementSibling.innerHTML = text;
e.previousElementSibling.src = imgSrc;
}
});
}
// 點擊掃一掃
document.getElementById('scan').onclick = function() {
getMedia();
};
</script>
</body>