js调用摄像头解析二维码
因为需求做一个扫码功能,发觉网上的资料不是不能用就是不完善,遂借鉴各种资料把这个功能搞出来了。
注意要点:
1、需要https验证通过才可以,
2、仅支持安卓端,iOS理论上也没问题的 但是 就是摄像头是前置摄像头没办法改,如果谁研究出来了,求告知
逻辑流程:网上给出了各种借助照相机的办法,方法很多,我觉得最合适我的属于,js获取摄像头设备,然后获取打开摄像头,获取视频流,输出到video,设定定时器,定时将视频流放到画布,设定定时器,利用qccode扫描解码画布,扫描成功,停止定时器,继续之后操作,结束
遇到的困难:
1、iOS无法后置摄像头问题
2、扫码识别率太低,解决办法:修改生成二维码宽高设置,模式修改,给二维码加白色边框
引入文件:https://pan.baidu.com/s/1tcijinlX2DGMkqv6WGaArw 提取码:9utf
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>教博会门票扫描器</title>
<script src="https://cdn.bootcss.com/vConsole/3.2.0/vconsole.min.js"></script>
<script type="text/javascript" src="js/llqrcode.js"></script>
<script>
let vConsole = new VConsole();
</script>
<style>
#scan {
position: fixed;
bottom: 5px;
left: 50%;
transform: translateX(-50%);
display: block;
text-decoration: none;
margin: 0 auto;
width: 100%;
line-height: 2.5rem;
text-decoration: none;
color: #fff;
text-align: center;
border-radius: 20px 20px 20px 20px;
font-size: .8rem;
background-color: #0E76E1;
}
#qr-canvas {
margin: 0px auto;
max-width: 300px;
}
#video{
margin: 0px auto;
}
</style>
</head>
<body>
<div id="output"></div>
<!-- 由于llqrcode.js中写死了id,所以id必须为qr-canvas -->
<video id="video" muted autoplay playsinline width="300" height="200"></video>
<canvas id="qr-canvas" style="display:none;"></canvas>
<a href="javascript:;" id="scan">扫码</a>
<script type="text/javascript">
const Scan = {
videoInputDevice: [],
videoElement: document.getElementById("video"),
canvasElement: document.getElementById("qr-canvas"),
decodeTimer: null,
canvasTimer: null,
canvasContext: document.getElementById("qr-canvas").getContext("2d"),
// 获取到的媒体设备
gotDevices (deviceInfos) {
let that = this;
for (let i = 0; i !== deviceInfos.length; ++i) {
let deviceInfo = deviceInfos[i];
if (deviceInfo.kind === 'audioinput') {
// 音频设备
} else if (deviceInfo.kind === 'videoinput') {
// 视频设备
that.videoInputDevice.push(deviceInfo);
} else {
// 其他设备
console.log('Found one other kind of source/device: ', deviceInfo);
}
}
},
getStream () {
let that = this;
if (window.stream) {
window.stream.getTracks().forEach((track) => {
track.stop();
});
}
// if(that.isIOS){
// let constraints = {
// video: { facingMode: { exact: "environment" } }
// };
// console.log('3: ', constraints);
// // let constraints = {
// // video: {
// // // environment表示后置摄像头
// // // user表示前置摄像头
// // facingMode: ("environment")
// // }
// // };
// }else{
let constraints = {
// 包含audio 可声明音频设备调用
// 声明视频设备调用
// video: true
video: {
deviceId: {
// [1].deviceId 表示后置摄像头,默认开启的是前置摄像头
exact: that.videoInputDevice[1].deviceId
}
}
};
// }
// 视频设备初始化
navigator.mediaDevices.getUserMedia(constraints).then(that.gotStream.bind(that)).catch(that.handleError.bind(that));
that.captureToCanvas();
that.decode();
},
// 解码
decode () {
let that = this;
try {
qrcode.decode();
} catch (e) {
console.log('1:'+e);
};
that.decodeTimer = setTimeout(that.decode.bind(that),100); // 解码频率为100毫秒一次
},
//将视频流放到画布
captureToCanvas () {
let that = this;
try {
// 根据视频大小设置canvas大小
let w = that.videoElement.videoWidth;
let h = that.videoElement.videoHeight;
that.canvasElement.width = w;
that.canvasElement.height = h;
that.canvasContext.drawImage(that.videoElement, 0, 0, w, h);
} catch (e) {
console.log(e);
};
// 100毫秒绘制一次
that.canvasTimer = setTimeout(that.captureToCanvas.bind(that),100);
},
handleError (error) {
console.log('Error: ', error);
},
gotStream (stream) {
let that = this;
window.stream = stream; // make stream available to console
that.videoElement.srcObject = stream;
},
isIOS(){
var u = navigator.userAgent;
var IOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
if(IOS){
return true;
}else{
return false;
}
},
init () {
let that = this;
// API参考
// https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/enumerateDevices
// 先获取设备列表,方便调用后置摄像头
let devices = navigator.mediaDevices.enumerateDevices().then(that.gotDevices.bind(that));
document.querySelector('#scan').addEventListener('click', () => {
document.getElementById('output').innerHTML = '';
that.videoElement.style.display = 'block';
// that.canvasElement.style.display = 'block';
that.videoElement.play();
devices.then(that.getStream.bind(that)).catch(that.handleError.bind(that));
that.canvasContext.clearRect(0, 0, 300, 200);
//结果回调
qrcode.callback = (e) => {
// 清除画布,停止摄像头
clearTimeout(that.decodeTimer);
clearTimeout(that.canvasTimer);
that.canvasContext.clearRect(0, 0, 300, 200);
if (window.stream) {
window.stream.getTracks().forEach((track) => {
track.stop();
});
}
that.videoElement.style.display = 'none';
that.canvasElement.style.display = 'none';
if(e.indexOf("http")!=-1){
window.location.href=e+'&token=xxxx';
}else {
document.getElementById('output').innerHTML = '结果:' + e;
}
}
});
}
};
Scan.init();
</script>
</body>
</html>
js调用摄像头解析二维码相关推荐
- C# 调用摄像头解析二维码
上次的二维码项目中,在解析的时候用的是扫码枪自动解析并以键盘形式输出,二次开发及通用性不高.本次项目使用AForge库调用摄像头采集二维码照片,再使用ZXing库解析二维码,较之前通用性更高. 一.调 ...
- html+js 调用摄像头识别二维码
1. html调起摄像头,参考文档:https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/getUserMedia 2.识别二维码 ...
- web/html5调用摄像头实现二维码扫描效果(代码实例)
本文给大家介绍如何用web/html5调用摄像头实现二维码扫描的效果,有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所帮助. 利用html5(navigator.getUserMedia)调 ...
- 【javascript】浏览器调用摄像头扫二维码踩坑记录
前言 最近做一个项目需要用浏览器调用摄像头扫二维码,然后就踩了几个坑记录下. 踩坑记录 我一开始发现了zxing这个库,他分为https://www.npmjs.com/package/@zxing/ ...
- PC端调用摄像头扫描二维码,拿到二维码信息
PC端调用摄像头扫描二维码,拿到二维码信息 <template><el-dialogtitle="扫描设备二维码":visible.sync="dial ...
- C#生成二维码、调用摄像头扫描二维码
二维码的生成和解码,有两个开源项目可以参考: 一个是google的zxing,另外一个是ThroughWork. zxing做的很全面,支持各种语言和平台,具体不多讲,自己查去.ThroughWork ...
- js调用微信利用二维码扫码登录
js调用微信利用二维码扫码登录 准备工作 网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统. 在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐 ...
- js 通过摄像头识别二维码,可以控制闪光灯。原生 HTML 调用摄像头,有 原生HTML + JS 版本 和 VUE3 + TS 版本与 uniapp 版本
开发背景 最开始公司说到这个需求的时候第一个想法是使用微信的 js SDK 接入微信的扫一扫.但是得知所做的这个功能模块是需要嵌入到之前开发的app中,所以就只有使用 js 原生的 API 来开发了. ...
- 使用摄像头解析二维码,且可以生成含具体信息的二维码
开源一份早些时候写过的代码,关于二维码在PC端的应用. 二维码的具体应用范围,这里不详述. 之前项目主要用于朋友一个牙科的平台,不过后面没有采用,也就没有往后继续开发,大家要是觉得有意思,可以自己拿去 ...
最新文章
- linux 本机内存型号,linux怎么看存储空间型号
- 大数据可以帮助企业获得资金吗?
- JavaScript中的call、apply、bind深入理解
- Javascript正则表达式难点、重点
- 为什么indexOf在数组IE8上不起作用?
- MySQL 8.0 可以操作 JSON 了,牛!
- 函数(一.return)
- Python3.6学习笔记(四)
- leetcode1070. 产品销售分析 III(SQL)
- System学习笔记007---win10连接阿里云出现_远程连接提示要求的函数不受支持如何解决
- 18Python标准库系列之logging模块
- Java中的关键字汇总(50个)
- 仪表盘故障图像识别_一目了然:汽车仪表盘上指示、警示、故障图标全解
- 腾讯微博开放平台授权教程(一)
- 微信小程序前台开发——实现登录,底部导航栏,顶部导航栏(分类显示)
- 中文短文本分类实例十四-LEAM(Joint Embedding of Words and Labels for Text Classification)
- UEBA对抗威胁之“健康就是财富”!
- 影像分析器之:波形示波器
- [MakeFile教程-09] 隐含规则
- 1M的宽带下载速度为什么不是1M