html+js调用手机摄像头扫描二维码(生产勿用!)

本文详细介绍如何在HTML5的APP项目中实现二维码扫描功能,包括必要的代码示例及资源链接,特别指出在不同设备及操作系统上的兼容性问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

qrcode.js 不支持直接调用手机摄像头扫描二维码,因为它本身是个用于生成和解析二维码的 JavaScript 库,无法直接访问摄像头。 如果需要在移动设备上调用摄像头扫描二维码,可以使用些第三方的 JavaScript 库,如 ZXing 或 QuaggaJS。 以下是个使用 QuaggaJS 调用摄像头扫描二维码的示例代码: ```javascript // 引入 QuaggaJS 库 import Quagga from 'quagga'; // 获取视频元素和结果元素 const video = document.getElementById('video'); const result = document.getElementById('result'); // 初始化 QuaggaJS Quagga.init({ inputStream : { name : "Live", type : "LiveStream", target: video }, decoder : { readers : ["code_128_reader", "ean_reader", "ean_8_reader", "code_39_reader", "code_39_vin_reader", "codabar_reader", "upc_reader", "upc_e_reader", "i2of5_reader"] } }, function(err) { if (err) { console.log(err); return; } console.log("QuaggaJS initialization succeeded"); // 开始扫描 Quagga.start(); // 监听扫描到的二维码 Quagga.onDetected((data) => { result.textContent = data.codeResult.code; }); }); ``` 在上述代码中,我们首先引入了 QuaggaJS 库,然后获取了视频元素和结果元素。接着,我们使用 `Quagga.init()` 方法初始化 QuaggaJS,将视频元素作为输入流,并指定需要识别的二维码类型。初始化完成后,我们使用 `Quagga.start()` 方法开始扫描,同时使用 `Quagga.onDetected()` 方法监听扫描到的二维码,将解码结果显示在结果元素中。 需要注意的是,使用 QuaggaJS 调用摄像头扫描二维码需要浏览器支持 WebRTC 技术,因此在些老旧的浏览器上可能无法正常工作。另外,在移动设备上使用摄像头扫描二维码时,需要请求用户授权访问摄像头
评论 40
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值