背景
扫描甲方商品身上的条形码。
吐槽下:这玩意又细又小,还反光,最后用的uni-app上的插件,而且不用自己封装了。虽然和我之前的二方案差不多,即使用
Quagga,打开video,将每帧画成canvas,然后转换为图片交给Quagga识别,缺点是功耗大,最后实装的表现还行,就是扫几个码,手机热了。回归正题,最开始用的zxing,虽然后面测试发现ios部分手机没有聚焦,巨拉。但还是记录下怎么做的吧。
最下面是全部代码。
事前准备
安装zxing插件,--save是保存到package.json中, webrtc-adapter也是。
npm install @zxing/library --save
npm install webrtc-adapter --save
解释
zxing 是js插件,webrtc是引用手机设备用的具体查看mdn文档
MediaDevices.getUserMedia() - Web API 接口参考 | MDN (mozilla.org)
中间遇见的问题
zxing创建的video视频清晰度太低,然后用了webrtc创建,但兼容性有问题,查找文章,做了个兼容性判断,然后发现画面太小了。
碎碎念:其实是条形码太小了,还不清晰,颜色太淡。
最后发现在定义video属性的时候加zoom就可调整缩放,然后本人安卓redmK60好使,但ios不行。
参考文章
(66条消息) Vue 扫描二维码、条形码_vue扫一扫条形码功能_aibujin的博客-CSDN博客
代码
<template> <div class="scan-page"> <!-- 扫码区域 --> <div class="video-box"> <video ref="video" class="scan-video" id="video" autoplay></video> </div> <!-- 扫码样式 --> <div class="qr-scanner"> <div class="box"> <div class="line"></div> <div class="angle"></div> </div> <div class="back-arrow" @click="goBack"> <span>返回</span> </div> </div> </div> </template> <script> // WebRTC适配器 只需要引入就ok import 'webrtc-adapter' import { BrowserMultiFormatReader } from '@zxing/library'; export default { name: 'ScanCodePage', // 扫码页面 data() { return { codeReader: null, // tipShow: false, // 是否展示提示 tipMsg: '', // 提示文本内容 scanText: '', // 扫码结果文本内容 visible: false, //提示信息显示 streaming: false, //初始化 deviceId: null, //摄像头id video: null } }, // 进入时的初始化 async mounted() { let arr = []; this.codeReader = await new BrowserMultiFormatReader(); navigator.mediaDevices.enumerateDevices() .then(function (devices) { devices.forEach(function (device) { if (device.kind === 'videoinput') { arr.push(device.deviceId) } }); }).finally(res => { this.deviceId = arr[arr.length - 1]; //后置摄像头一般为最后一个,也可以在constraints中定义为后置摄像头,具体参数请查看mdn文档 this.init(); }) }, // 销毁时的还原 beforeDestroy() { this.codeReader.reset(); this.codeReader = null; }, methods: { init() { // 初始化摄像头 this.video = document.querySelector('#video'); let constraints = { video: { deviceId: this.deviceId, width: { min: 800, ideal: 1600 }, height: { min: 600, ideal: 1200 }, advanced: [ { width: 1200, height: 900 }, { aspectRatio: 1.33 } ], zoom: 3 //只有部分手机生效,苹果不生效 }, audio: false } this.getUserMedia(constraints, this.getUserMediaSuccess, this.getUserMediaError) this.video.addEventListener('canplay', (ev) => { if (!this.streaming) { this.height = this.video.videoHeight / (this.video.videoWidth / this.width); if (isNaN(this.height)) { this.height = this.width / (4 / 3); } this.video.setAttribute('width', this.width); this.video.setAttribute('height', this.height); this.streaming = true; } }, false); this.decodeFromInputVideoFunc(); }, decodeFromInputVideoFunc() { // 使用摄像头扫描 this.codeReader.reset(); // 重置 this.codeReader.decodeFromInputVideoDeviceContinuously(this.deviceId, 'video', (result, err) => { this.tipMsg = '正在尝试识别...'; if (result) { console.log('扫码结果', result); this.scanText = result.text; alert(this.scanText) if (this.scanText) { this.visible = true alert(this.scanText+'==='+this.visible) console.log() } } console.log(err) }).catch(err => { console.log(err) }); }, // 浏览器适配 这个参考了简书上的文章,找不到原文了 getUserMedia(constraints, success, error) { if (navigator.mediaDevices.getUserMedia) { //最新的标准API navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error); } else if (navigator.webkitGetUserMedia) { //webkit核心浏览器 navigator.webkitGetUserMedia(constraints, success, error) } else if (navigator.mozGetUserMedia) { //firfox浏览器 navigator.mozGetUserMedia(constraints, success, error); } else if (navigator.getUserMedia) { //旧版API navigator.getUserMedia(constraints, success, error); } }, //获取设备成功的方法 getUserMediaSuccess(stream) { console.log(stream); }, //获取设备失败的重写方法 getUserMediaError(error) { console.log(`访问用户媒体设备失败${error.name}, ${error.message}`); }, goBack() { // 返回上一页 this.$destroy(); this.$router.go(-1); }, } } </script> <style lang="scss" scoped > .video-box { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; height: 20%; } .scan-video { width: 100%; height: 100%; object-fit: cover; } .scan-page { min-height: 100vh; background-color: #363636; .scan-tip { width: 100vw; position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); text-align: center; color: white; font-size: 5vw; } .qr-scanner { background-image: linear-gradient(0deg, transparent 24%, rgba(32, 255, 77, 0.1) 25%, rgba(32, 255, 77, 0.1) 26%, transparent 27%, transparent 74%, rgba(32, 255, 77, 0.1) 75%, rgba(32, 255, 77, 0.1) 76%, transparent 77%, transparent), linear-gradient(90deg, transparent 24%, rgba(32, 255, 77, 0.1) 25%, rgba(32, 255, 77, 0.1) 26%, transparent 27%, transparent 74%, rgba(32, 255, 77, 0.1) 75%, rgba(32, 255, 77, 0.1) 76%, transparent 77%, transparent); background-size: 0.3rem 0.3rem; background-position: -1rem -1rem; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 9; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); } .qr-scanner .box { width: 90%; height: 20%; max-height: 75vh; max-width: 75vh; position: relative; left: 50%; top: 50%; transform: translate(-50%, -50%); overflow: hidden; border: 0.02rem solid rgba(0, 255, 51, 0.2); } .qr-scanner .line { height: calc(100% - 2px); width: 100%; background: linear-gradient(180deg, rgba(0, 255, 51, 0) 43%, #00ff33 211%); border-bottom: 3px solid #00ff33; transform: translateY(-100%); animation: radar-beam 2s infinite; animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99); animation-delay: 1.4s; } .qr-scanner .box:after, .qr-scanner .box:before, .qr-scanner .angle:after, .qr-scanner .angle:before { content: ''; display: block; position: absolute; width: 3vw; height: 3vw; border: 0.02rem solid transparent; } .qr-scanner .box:after, .qr-scanner .box:before { top: 0; border-top-color: #00ff33; } .qr-scanner .angle:after, .qr-scanner .angle:before { bottom: 0; border-bottom-color: #00ff33; } .qr-scanner .box:before, .qr-scanner .angle:before { left: 0; border-left-color: #00ff33; } .qr-scanner .box:after, .qr-scanner .angle:after { right: 0; border-right-color: #00ff33; } @keyframes radar-beam { 0% { transform: translateY(-100%); } 100% { transform: translateY(0); } } .back-arrow { position: fixed; top: 10px; left: 10px; width: 100px; height: 50px; // border-radius: 100%; // background-color: rgba(0, 0, 0, 0.3); font-size: 20px; z-index: 999; display: flex; justify-content: center; align-items: center; color: #fff; } } </style>
标签:条形码,vue,scanner,height,width,qr,video,rgba,zxing From: https://www.cnblogs.com/piaohd/p/17563435.html