ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Vue+zxing实现扫二维码、条形码功能

2022-09-05 16:01:12  阅读:192  来源: 互联网

标签:条形码 Vue scanner 100% value zxing rgba height transparent


<script setup >
import { ref, reactive, toRefs } from 'vue'
import { BrowserMultiFormatReader  } from '@zxing/library';
import { Dialog, Notify } from 'vant';
import { useRouter, useRoute } from "vue-router"
const router = useRouter()
const data = reactive({
    loadingShow: false,
    codeReader: null,
    scanText: '',
    vin: null,
    tipMsg: '正在尝试识别....',
    tipShow: false
})
const { loadingShow, codeReader, scanText, vin, tipMsg, tipShow } = toRefs(data);
codeReader.value = new BrowserMultiFormatReader();

openScan();
function openScan() {
    codeReader.value.getVideoInputDevices().then((videoInputDevices) => {
        tipShow.value = true;
        tipMsg.value = '正在调用摄像头...';
        console.log('videoInputDevices', videoInputDevices);
        // 默认获取第一个摄像头设备id
        let 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;
            }
        }
        decodeFromInputVideoFunc(firstDeviceId);
    }).catch(err => {
        tipShow.value = false;
        console.error(err);
    });
}

function decodeFromInputVideoFunc(firstDeviceId) {
    codeReader.value.reset(); // 重置
    scanText.value = '';
    codeReader.value.decodeFromInputVideoDeviceContinuously(firstDeviceId, 'video', (result, err) => {
        tipMsg.value = '正在尝试识别...';
        scanText.value = '';
        if (result) {
            console.log('扫描结果', result);
            scanText.value = result.text;
            if (scanText.value) {
                tipShow.value = false;
                clickIndexLeft()
                // 这部分接下去的代码根据需要,读者自行编写了
                // this.$store.commit('app/SET_SCANTEXT', result.text);
                // console.log('已扫描的小票列表', this.$store.getters.scanTextArr);
            }
        }
        if (err && !(err)) {
            tipMsg.value = '识别失败';
            setTimeout(() => {
                tipShow.value = false;
            }, 2000)
            console.error(err);
        }
    });
}
function clickIndexLeft(){
  console.log("我要传参了",scanText.value)
   router.replace({
         name:'work',
         params:{
            result:scanText.value
         }
   })
    codeReader.value.reset(); // 重置
}
const onClickRight = () => Toast('按钮');
</script>
<template>
    <div class="page-scan">
        <!--返回-->
        <!-- <van-nav-bar title="扫描二维码/条形码" fixed @click-left="clickIndexLeft()" class="scan-index-bar">
            <template #left>
                <van-icon name="arrow-left" size="18" color="#fff" />
                <span style="color: #fff"> 取消 </span>
            </template>
        </van-nav-bar> -->
        <van-nav-bar
        title="扫描二维码/条形码"
        right-text="按钮"
        left-arrow
         fixed
        @click-right="onClickRight"
         @click-left="clickIndexLeft()"
        />
        <!-- 扫码区域 -->
        <!-- <video ref="video" id="video" class="scan-video" autoplay></video> -->

    <div class="QrCode">
      <video ref="video" height="100%" width="100%" id="video" autoplay></video>
    </div>
    <!-- 扫码样式一 -->
    <div class="Qr_scanner">
      <div class="box">
        <div class="line_row">
          <div class="line"></div>
        </div>
        <div class="angle"></div>
      </div>
    </div>


        <!-- 提示语 -->
        <div>{{scanText}}</div>
        <div v-show="tipShow" class="scan-tip"> {{ tipMsg }} </div>
    </div>
</template>
<style scoped lang="scss">

/* .scan-video {
    height: 80vh;
    width: 100%
}

.scan-tip {
    width: 50vw;
    text-align: center;
    margin-bottom: 10vh;
    color: white;
    font-size: 5vw;
}

.page-scan {
    overflow-y: hidden;
    background-color: #363636;
} */



/**
  扫码样式一
*/
.QrCode {
  width: 100vw;
  height: 100vh;
  position: relative;
  #video {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}

 
.Qr_scanner {
  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: 75vw;
  height: 75vw;
  max-height: 75vh;
  max-width: 75vh;
  position: relative;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  border: 1px solid rgb(43, 113, 254);
  .line_row {
    width: 100%;
    overflow: hidden;
    background-image: linear-gradient(
        0deg,
        transparent 24%,
        rgba(136, 176, 255, 0.1) 25%,
        rgba(136, 176, 255, 0.1) 26%,
        transparent 27%,
        transparent 74%,
        rgba(136, 176, 255, 0.1) 75%,
        rgba(136, 176, 255, 0.1) 76%,
        transparent 77%,
        transparent
      ),
      linear-gradient(
        90deg,
        transparent 24%,
        rgba(136, 176, 255, 0.1) 25%,
        rgba(136, 176, 255, 0.1) 26%,
        transparent 27%,
        transparent 74%,
        rgba(136, 176, 255, 0.1) 75%,
        rgba(136, 176, 255, 0.1) 76%,
        transparent 77%,
        transparent
      );
    background-size: 3rem 3rem;
    background-position: -1rem -1rem;
    animation: Heightchange 2s infinite;
    animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99);
    animation-delay: 1.4s;
    border-bottom: 1px solid rgba(136, 176, 255, 0.1);
    display: flex;
    justify-content: center;
    align-items: flex-end;
  }
}
.Qr_scanner .line {
  width: 100%;
  height: 3px;
  background: #2b71fe;
  // opacity: 0.58;
  filter: blur(4px);
}
.Qr_scanner .box:after,
.Qr_scanner .box:before,
.Qr_scanner .angle:after,
.Qr_scanner .angle:before {
  content: "";
  display: block;
  position: absolute;
  width: 78px;
  height: 78px;
  border: 0.3rem solid transparent;
}
.Qr_scanner .box:after,
.Qr_scanner .box:before {
  top: -7px;
  border-top-color: #2b71fe;
}
.Qr_scanner .angle:after,
.Qr_scanner .angle:before {
  bottom: -7px;
  border-bottom-color: #2b71fe;
}
.Qr_scanner .box:before,
.Qr_scanner .angle:before {
  left: -7px;
  border-left-color: #2b71fe;
}
.Qr_scanner .box:after,
.Qr_scanner .angle:after {
  right: -7px;
  border-right-color: #2b71fe;
}
@keyframes radar-beam {
  0% {
    transform: translateY(-100%);
  }
  100% {
    transform: translateY(0);
  }
}
@keyframes Heightchange {
  0% {
    height: 0;
  }
  100% {
    height: 100%;
  }
}
 

</style>

使用的vue3.2 实现的扫码组件封装 样式一

<script setup >
import { ref, reactive, toRefs } from 'vue'
import { BrowserMultiFormatReader  } from '@zxing/library';
import { Dialog, Notify } from 'vant';
import { useRouter, useRoute } from "vue-router"
const router = useRouter()
const data = reactive({
    loadingShow: false,
    codeReader: null,
    scanText: '',
    vin: null,
    tipMsg: '正在尝试识别....',
    tipShow: false
})
const { loadingShow, codeReader, scanText, vin, tipMsg, tipShow } = toRefs(data);
codeReader.value = new BrowserMultiFormatReader();

openScan();
function openScan() {
    codeReader.value.getVideoInputDevices().then((videoInputDevices) => {
        tipShow.value = true;
        tipMsg.value = '正在调用摄像头...';
        console.log('videoInputDevices', videoInputDevices);
        // 默认获取第一个摄像头设备id
        let 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;
            }
        }
        decodeFromInputVideoFunc(firstDeviceId);
    }).catch(err => {
        tipShow.value = false;
        console.error(err);
    });
}

function decodeFromInputVideoFunc(firstDeviceId) {
    codeReader.value.reset(); // 重置
    scanText.value = '';
    codeReader.value.decodeFromInputVideoDeviceContinuously(firstDeviceId, 'video', (result, err) => {
        tipMsg.value = '正在尝试识别...';
        scanText.value = '';
        if (result) {
            console.log('扫描结果', result);
            scanText.value = result.text;
            if (scanText.value) {
                tipShow.value = false;
                clickIndexLeft()
                // 这部分接下去的代码根据需要,读者自行编写了
                // this.$store.commit('app/SET_SCANTEXT', result.text);
                // console.log('已扫描的小票列表', this.$store.getters.scanTextArr);
            }
        }
        if (err && !(err)) {
            tipMsg.value = '识别失败';
            setTimeout(() => {
                tipShow.value = false;
            }, 2000)
            console.error(err);
        }
    });
}
function clickIndexLeft(){
  console.log("我要传参了",scanText.value)
   router.replace({
         name:'work',
         params:{
            result:scanText.value
         }
   })
    codeReader.value.reset(); // 重置
}
const onClickRight = () => Toast('按钮');
</script>
<template>
    <div class="page-scan">
        <!--返回-->
        <!-- <van-nav-bar title="扫描二维码/条形码" fixed @click-left="clickIndexLeft()" class="scan-index-bar">
            <template #left>
                <van-icon name="arrow-left" size="18" color="#fff" />
                <span style="color: #fff"> 取消 </span>
            </template>
        </van-nav-bar> -->
        <van-nav-bar
        title="扫描二维码/条形码"
        right-text="按钮"
        left-arrow
         fixed
        @click-right="onClickRight"
         @click-left="clickIndexLeft()"
        />
   <!-- 扫码区域 -->
    <div class="QrCode">
      <video ref="video" height="100%" width="100%" 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="clickIndexLeft">
        <van-icon name="arrow-left" color="#fff" />
      </div>
    </div>
  </div>


        <!-- 提示语 -->
        <div>{{scanText}}</div>
        <div v-show="tipShow" class="scan-tip"> {{ tipMsg }} </div>
</template>
<style scoped lang="scss">
.QrCode {
  width: 100vw;
  height: 100vh;
  position: relative;
  #video {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}


/**
  扫码样式二
*/
.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: 3rem 3rem;
  background-position: -1rem -1rem;
  // width: 100%;
  // height: 100%;
  // position: relative;
  // background-color: #111;
 
  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: 75vw;
  height: 75vw;
  max-height: 75vh;
  max-width: 75vh;
  position: relative;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  overflow: hidden;
  border: 0.1rem 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.2rem 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);
  }
}
 
.qr-scanner .back-arrow {
  position: fixed;
  top: 20px;
  left: 20px;
  width: 30px;
  height: 30px;
  border-radius: 100%;
  background-color: rgba(0, 0, 0, 0.3);
  z-index: 999;
 
  display: flex;
  justify-content: center;
  align-items: center;
}

</style>

 样式二

 

标签:条形码,Vue,scanner,100%,value,zxing,rgba,height,transparent
来源: https://www.cnblogs.com/ddqyc/p/16658475.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有