一、场景

手机移动端-原生js 浏览器h5 解决 识别二维码 条形码功能;

不借助Hbuilder.需要自己打包成APP,比如用Hbuilder打包,浏览器端项目h5 无打包成app部署 X 不采用

不借助微信扫一扫,调用微信js-jdk有多麻烦,还要认证服务号,也不适用 其它浏览器打开 X 不采用

二、思路

1.思路一:input(相机拍照)+ 条形码或二维码识别js支持库

通过h5-input[camera] 调用相机进行拍照成图片,通过条形码等识别库 解析出 数据;

<input @change="toQR"  type="file" accept="image/*" capture="camera">

1-1.方案一:input+ Quagga识别库,success, 可识别 条形码,不能识别二维码;

quagga库地址 https://www.npmjs.com/package/quagga

npm install quagga --save

1-2.方案二:input+jsqr识别库,success,可识别条形码,也可识别二维码,但二维码识别很局限性,如果只做条形码识别可采用,若是识别二维码不适用;

jsqr库地址 https://www.npmjs.com/package/jsqr

npm install jsqr --save

例: 1.正方形不带其它无效内容 只二维码的图片,设置jsqr识别长宽 100*100 ,可成功识别

       2.长方形带其它无效内容,比如拍照出来的二维码图片,设置jsqr识别长宽 自适(传入图片的长宽 或100*100),都识别失败

1-3.方案三: input+qrcode库, 失败

qrcode.decode(img)

2.思路二:调用摄像头(video动态识别)+ 条形码或二维码识别js支持库

调用手机原生摄像头 动态识别 用相关支持js库  解析 二维码 条形码

2-1.方案四:video+ zxing识别库,success,可识别 条形码 可识别二维码,完美解决,楼主采用的这种;

zxing-js/library库地址 https://github.com/zxing-js/library

npm install  @zxing/library --save

三、实例

1-1.方案一

vue-demo

<template><div class="mt46 input-cells"><div class="flex a-center f-fl"><div>车架号</div><input v-model="queryParams.vin" class="cell-input ml5 mr10" type="text"placeholder="请输入或扫描拍照" /></div><div class="flex l-center a-left"><div class="qr-item mr5 ml5"><!--图标自用 https://www.iconfont.cn/ --> <!--<i class="iconfont icon-qr f18 c-ffaa09"></i>--><img src="#" width="20" height="20" alt=""><input v-if="isUploadBarCode" class="qr-item-input" @change="toQR"  type="file" accept="image/*" capture="camera"></div></div></div>
</template>
<style scoped>.input-cells{display: flex;justify-content:space-between;align-items: center;position: relative;background-color: #fff;overflow: hidden;padding: .06rem .15rem;height: .32rem;line-height: .32rem;font-size: .14rem;}.input-label{margin-left: 0;font-size: .14rem;width: .9rem;}.input-cells>input{font-size: .14rem;text-align: right;}.input-cells>img{width: .06rem;height: .1rem;margin-right: .03rem;}.qr-item{width: .3rem;height: 100%;background-size: 120%;position: relative;overflow: hidden;border: 1px solid #dae7f6;background-color: #f5f5f5;}.qr-item-input{opacity: 0;width: 100%;height: 100%;background-size: 100%;position: absolute;top: 0;left: 0;}/*common*/.flex{display: flex;}.a-center{align-items: center;}.f-fl{float: left;}.ml5{margin-left: .05rem;}.mr10{margin-right: .1rem;}
</style>

es6引入使用

 import Quagga from 'quagga'

使用

<script type="text/ecmascript-6">import Quagga from 'quagga'export default {name: '',data() {return {queryParams: {vin: null},isUploadBarCode: true, // 控制销毁}},mounted() {},methods: {// 图片 识别 条形码toQR(e) {const that = thisconst file0 = e.target.files[0]// console.log('toQR()-file0', file0)this.isUploadBarCode = falseQuagga.decodeSingle({inputStream: {name : 'image',type : 'ImageStream',// size: 1600, // 这里指定图片的大小,需要自己测试一下singleChannel: false,},locator: {patchSize: 'medium',halfSample: false},numOfWorkers: 1,decoder: { // ean_reader 这里指定ean条形码,就是国际13位的条形码   code39    code_128readers: ['code_128_reader']},// readers: ['code_128_reader'],locate: true,src: URL.createObjectURL(file0)},(result) => {console.log('Quagga()-result', result)// let code = result.codeResult.codeif (result && result.codeResult) {that.queryParams.vin = result.codeResult.code// 执行 页面请求刷新} else {that.queryParams.vin = nullconsole.warn('识别失败,请手动输入')}this.isUploadBarCode = true})},}}
</script>

1-2.方案二

方案二 html+css 公用与 方案一

qrcodeSearch.js

// import QRCode from '../libs/qr/qrcode'
import jsqr from 'jsqr'
// 二维码 或 条形码 识别
export function showQrCode(file, params, callback) {const ready = new FileReader()/* 开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.*/ready.readAsDataURL(file) // 调用reader.readAsDataURL()方法,把图片转成base64ready.onload = function() {const re = this.resultcanvasDataURL(re, params, callback)}
}
function canvasDataURL(path, obj, callback) {const img = new Image()img.src = path// 生成canvasconst canvas = document.createElement('canvas')// const canvas = document.getElementById('qrcanvas')const ctx = canvas.getContext('2d')// const _this = thisimg.onload = function() {console.log('canvasDataURL()-img', img.height, img.width)// let w = img.width// let h = img.heightconst w = 100const h = 100ctx.clearRect(0, 0, w, h)ctx.drawImage(img, 0, 0, w, h);const imageData = ctx.getImageData(0, 0, w, h);const code = jsqr(imageData.data, w, h);const res = {data: null,message: '识别成功',code: 0,}if(code){res.data = code.datacallback(res)}else{res.code = -1res.data = nullres.message = '识别失败'callback(res)}}
}

使用

<script type="text/ecmascript-6">import * as QrCode from './qrcodeSearch'export default {name: '',data() {return {queryParams: {vin: null},isUploadBarCode: true, // 控制销毁}},mounted() {},methods: {// 图片 识别 条形码toQR(e) {const that = thisconst file0 = e.target.files[0]// console.log('toQR()-file0', file0)this.isUploadBarCode = falseQrCode.showQrCode(file0, {}, function (res) {this.isUploadBarCode = trueconsole.log('showQrCode()-res', res)if (res.code === 0) {that.queryParams.vin = res.data} else {console.warn('识别失败,请手动输入')}})},}}
</script>

2-1.方案四

注意,因为调用原生摄像头 要在 https环境下,故需要把代码发布到 带域名(https)的测试环境 进行调试【这是必要的前提条件,没有测试环境就不要整了】。故而代码调整要反复发布构建代码,不过楼主的这个例子已经是整好了的;

vue-demo

<template><div class="page bgc-f4f4f4"><!--路由返回--><!--<lisa-header title="扫描二维码"></lisa-header>--><video ref="video" id="video" class="video vjs-fluid" autoplay></video><div v-show="tipShow" class="tip">{{tipMsg}}</div></div>
</template>
<style scoped>/*vjs-fluid 自适video 长宽*/.video{/*border: 1px solid gray;*/margin-top: .5rem;/*width: 2.6rem;*//*height: 3rem;*/}.tip{color: white;font-size: .16rem;}/* common */.bgc-f4f4f4{background-color: #363636;}.page{overflow-y: auto;position: relative;}
</style>

使用

<script type="text/ecmascript-6">import { MessageBox } from 'mint-ui'import { BrowserMultiFormatReader } from '@zxing/library'export default {name: 'qr-code-search',components: {},data() {return {loadingShow: false,codeReader: new BrowserMultiFormatReader(),textContent: null,vin: null,tipMsg: '正在尝试识别....',tipShow: false}},created() {// this.tipShow = truethis.openScan()},methods: {async openScan() {const that = thisthat.codeReader.getVideoInputDevices().then((videoInputDevices) => {that.tipShow = truethat.tipMsg = '正在调用后置摄像头...'console.log('videoInputDevices', videoInputDevices);// 默认获取第一个摄像头设备idlet firstDeviceId = videoInputDevices[0].deviceId;// 获取第一个摄像头设备的名称const videoInputDeviceslablestr = JSON.stringify(videoInputDevices[0].label);if (videoInputDevices.length > 1) {// 判断是否后置摄像头if (videoInputDeviceslablestr.indexOf('back') > -1) {firstDeviceId = videoInputDevices[0].deviceId;} else {firstDeviceId = videoInputDevices[1].deviceId;}}that.decodeFromInputVideoFunc(firstDeviceId)}).catch((err) => {that.tipShow = falseconsole.error(err);});},async openScanTwo() {const that = this// codeReader.reset() // 重置// that.textContent = null // 重置that.codeReader = await new BrowserMultiFormatReader()that.codeReader.getVideoInputDevices().then((videoInputDevices) => {that.tipShow = truethat.tipMsg = '正在调用后置摄像头...'console.log('videoInputDevices', videoInputDevices);// 默认获取第一个摄像头设备idlet firstDeviceId = videoInputDevices[0].deviceId;// 获取第一个摄像头设备的名称const videoInputDeviceslablestr = JSON.stringify(videoInputDevices[0].label);if (videoInputDevices.length > 1) {// 判断是否后置摄像头if (videoInputDeviceslablestr.indexOf('back') > -1) {firstDeviceId = videoInputDevices[0].deviceId;} else {firstDeviceId = videoInputDevices[1].deviceId;}}that.decodeFromInputVideoFunc(firstDeviceId)}).catch((err) => {that.tipShow = falseconsole.error(err);});},decodeFromInputVideoFunc(firstDeviceId) {const that = thisthat.codeReader.reset() // 重置that.textContent = null // 重置that.codeReader.decodeFromInputVideoDeviceContinuously(firstDeviceId, 'video', (result, err) => {that.tipMsg = '正在尝试识别...'// let nowContent = nullthat.textContent = nullif (result) {console.log(result);that.textContent = result.text;if (that.textContent) {that.tipShow = falsethat.msgBoxFunc(that.textContent)}}if (err && !(err)) {that.tipMsg = '识别失败'setTimeout(() => {that.tipShow = false},2000)console.error(err);}});},// that.$createDialog 是 cube-ui滴滴 messageBox ,到这一步 二维码值已出,这里是可有可无的代码块,看各自项目ui使用情况 自行替换 messageBoxmsgBoxFunc(textContent) {const that = this// alert('8执行了 msgBoxFunc(),textContent:' + textContent)// cube-ui messageBoxthat.$createDialog({type: 'prompt',// icon: 'cubeic-alert',title: '识别内容',// content: that.textContent,prompt: {value: textContent,placeholder: '请输入'},confirmBtn: {text: '确定内容',active: true,disabled: false,href: 'javascript:;'},cancelBtn: {text: '继续识别',active: false,disabled: false,href: 'javascript:;'},onConfirm: (e, promptValue) => {// that.hide()console.log('onConfirm: ()')that.vin = promptValue},onCancel: () => {console.log('onCancel: ()')that.$nextTick(()=>{that.openScanTwo()})}}).show()},// msgBoxFunc2() 整块代码是mint-ui  messageBox示例用,此处未使用,可直接注释;msgBoxFunc2(textContent) {// mint-ui  messageBox  有重复 inputValue值问题,新调用 显示是旧的值const that = this// alert('8执行了 msgBoxFunc(),textContent:' + textContent)MessageBox.prompt('识别内容', {inputValidator: (val) => {if (val === null) {return true;//初始化的值为null,不做处理的话,刚打开MessageBox就会校验出错,影响用户体验}},confirmButtonText: '确定内容',cancelButtonText: '继续识别',inputValue: textContent,}).then(({value, action}) => {if (action === 'confirm') {that.vin = value}if (action === 'cancel') {that.$nextTick(()=>{that.openScanTwo()})}}).catch(err => {console.log(err);})}}}
</script>

四、尾结

道路过程是曲折坎坷的,结果是良好的,以为整不出来的然后柳暗花明;

参考文章:

https://www.jianshu.com/p/30a34157c7d1    zing-js/library

https://blog.csdn.net/aoshilang2249/article/details/105222706   MediaDevices.getUserMedia undefined 的问题

https://blog.csdn.net/yingzhi3104/article/details/105557591 quagga识别条形码图片

https://blog.csdn.net/qq_37705048/article/details/79816438 qrcode.js的识别

https://blog.csdn.net/haiyang5233233/article/details/105874129 调用摄像头是提示 navigator.mediaDevices.getUserMedia

https://blog.csdn.net/weixin_30260399/article/details/96458034 调用后置摄像头问题

手机移动端-纯js浏览器h5调用摄像头扫描识别解析 条形码+二维码相关推荐

  1. JS生成条形码/二维码 barcode.js、JsBarcode

    JS生成条形码/二维码 barcode.JsBarcode JsBarcode Barcode.js 以下代码均非纯原创.新手小白.网上一搜一大把的概念也不写了,直接上可运行的代码及遇到的小坑. Js ...

  2. Html+js:识别多个二维码并发送链接

    内容: 选择二维码图片识别,第一张图片为url ,连接地址发送二维码内容 支持识别多个二维码 支持连接接口 支持发送数据 支持展示数据 不支持手机 <!DOCTYPE html> < ...

  3. 基于SpringBoot+Gradle+Zxing+JQuery(原生JS)开发条形码/二维码扫描工具,且采用原生JS调用浏览器摄像头

    零. 近日在做课设的时候,碰到一个比较有趣的玩意.就是在应用上添加扫描二维码/条形码的技术. 下面,介绍一下本文采用的一些框架: SpringBoot+Gradle+JPA为框架的后端系统 JavaS ...

  4. uni-app H5+ 连接蓝牙打印机打印文字及二维码

    基于Native.js 实现的连接蓝牙打印机 打印效果图 核心代码 测试代码 运行设备及环境 PS: PPS: Demo 打印效果图 核心代码 /*** @Description: 蓝牙打印类 基于h ...

  5. JS使用Lodop控件打印表单和二维码

    有关Lodop的查询可看文章:Lodop打印条码二维码设置多宽不一定是多宽 一.了解Lodop 1.1Lodop的定义 Lodop(标音:劳道谱,俗称:露肚皮)是专业WEB控件,用它既可裁剪输出页面内 ...

  6. 手机扫描条形码二维码原理和实现等网上资料整理

    有志于要从事条形码和二维码开发的同学,和我一样想多了解这方面的东西.但是苦于网上资源甚少,我已经把现有资源整理如下. 原理.实现方案.代码资源.规则是否通用比如加密如何实现? ============ ...

  7. uniapp中H5网页和打包app分别生成二维码

    一.h5网页中生成二维码业务 引入"qrcodejs2.js":npm install qrcodejs2: <template><view><vie ...

  8. Java调用TSC条码打印机接口打印条码和二维码

    公司新买了一台TSC条码打印机,型号:TSC TTP-244 PRO,让和现有资产管理系统对接,可以根据系统上的编码直接打印. 研究了几天,终于调试出来了,下边是代码,,目测可用: java后台调试代 ...

  9. H5页面canvas绘制多张图片和二维码生成

    vue的h5页面生成canvas海报图,要求绘制一张背景底图,在背景图上绘制头像,文字和二维码,最后合成一张图片 npm install --save qrcode 下载生成二维码的依赖包 <t ...

最新文章

  1. 云计算&大数据 “下一幕”智能变革之力
  2. php下session入memcached
  3. 2012年的第一天 自己独自踏上回家的路 木有任何人相送
  4. linux与unix时间戳互转
  5. 幂等校验是什么意思_阿里面试官:接口的幂等性怎么设计?
  6. OpenCASCADE:函数机制的使用
  7. 孩子觉得数学难?那是底子没打好!
  8. Javamysql语法转化oracle_MySQL与Oracle的语法区别详细对比
  9. dao层和service层和control_最受欢迎Java数据库访问框架(DAO层)
  10. aspose excel中文文档_Excel实战技巧,如何将阿拉伯数字快速转换为中文大小写格式?...
  11. SQL Server使用convert对datetime日期数据进行获取
  12. CCIE试验备考之交换VLAN间路由
  13. vscode安装使用教程
  14. 地方科技局重点科技项目在线申报管理系统
  15. python批量关键字百度搜索结果url解码
  16. Android Gradle进阶配置指南 1
  17. 二项式反演(广义容斥定理)学习笔记
  18. OpenGL ES 基础概念
  19. 要怎么在计算机里清除桌面内存,怎么清理运行内存占用_怎么清理电脑运行内存-win7之家...
  20. Linux Bash常用的脚本工具整理

热门文章

  1. 编程的几种境界与招式
  2. 七牛云 X 英语流利说:教育 3.0 时代的智能突破
  3. 摸鱼方法合集(无需编程基础)
  4. GRBL V1.1f源码中文注解--GCode篇
  5. 中国车企出海,无人驾驶的聚光灯落在“车”上
  6. JIRA-使用教程_工作流_创建、方案配置
  7. bit、位、byte、B、字节、字符等换算
  8. 【悲观锁与乐观锁的原理及实现】
  9. NodeJS 搭建一个本地的服务,实现一个简单的公屏发消息
  10. java代码一括改包名_长安成人高考不考