html+js調用手機攝像頭掃描二維碼(生產勿用!)

在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>

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