条码扫描器

介绍

条码扫描器,又称为条码阅读器、条码扫描枪条形码扫描器、条形码扫描枪及条形码阅读器。它是用于读取条码所包含信息的阅读设备,利用光学原理,把条形码的内容解码后通过数据线或者无线的方式传输到电脑或者别的设备。广泛应用于超市、物流快递、图书馆等扫描商品、单据的条码

插件安装命令

npm install @zxing/library

代码部分

<template>
    <div class="code-reader-content">
        <div class="page">
            <video ref="video" autoplay id="video" height="200"></video>
            <p v-if="videoInputDevicesArray.length === 0">{{ textContent }}</p>
        </div>
        <div class="scan-box">
            <div class="frame upper-left"></div>
            <div class="frame upper-right"></div>
            <div class="frame lower-right"></div>
            <div class="frame lower-left"></div>
            <div class="pointer-box">
                <div class="pointer"></div>
            </div>
            <div v-show="tipShow" class="tip">{{ tipMsg }}</div>
            <div class="btn-switch" @click="toggle"></div>
            <button @click="handleScanComplete" class="btn-wc">扫描完成</button>
        </div>
    </div>
</template>

功能部分

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { BrowserMultiFormatReader } from '@zxing/library';

import { useRouter } from 'vue-router'
const router = useRouter()
import { defineEmits } from 'vue';

const emits = defineEmits(['scan-complete']);

const handleScanComplete = (val1) => {
    console.log('扫描完成按钮被点击了');
    emits('scan-complete', true, val1);
};

const codeReader = ref(null);
const tipMsg = ref('正在尝试识别....');
const tipShow = ref(true);
const textContent = ref(undefined);
const videoInputDevicesArray = ref([]);
const deviceId = ref('');
const isEswitch = ref(false);
let timer = null;

// 开启扫描
const openScan = async () => {
    codeReader.value = await new BrowserMultiFormatReader();
    codeReader.value
        .getVideoInputDevices()
        .then(async (videoInputDevices) => {
            tipShow.value = true;
            tipMsg.value = '正在尝试识别....';
            videoInputDevicesArray.value = videoInputDevices;
            if (videoInputDevicesArray.value.length > 1) {
                deviceId.value = videoInputDevicesArray.value[1].deviceId;
            } else {
                deviceId.value = videoInputDevicesArray.value[0].deviceId;
            }

            decodeFromInputVideoFunc();
            console.log('codeReader', codeReader.value);
            console.log('----------------');
            console.log('deviceId', deviceId.value);
            console.log('-------------------');
            console.log('videoInputDevicesArray', videoInputDevicesArray.value);
        })
        .catch(() => {
            tipShow.value = false;
        });
};

// 解码部分
const decodeFromInputVideoFunc = () => {
    if (videoInputDevicesArray.value.length === 0) {
        textContent.value = '初始化摄像头失败';
        document.getElementById('video').style.display = 'none';
        return;
    }

    codeReader.value.reset();
    codeReader.value.decodeFromInputVideoDeviceContinuously(
        deviceId.value,
        'video',
        (result) => {
            tipMsg.value = '正在扫描';
            if (result) {
                tipMsg.value = '扫描成功!';
                setTimeout(() => {
                    tipMsg.value = '解析完成';
                    handleScanComplete(result.text)
                }, 1000); // 延迟1秒钟
                console.log('扫描成功123', result);
                console.log('result123', result.text);
                // tipShow.value = false;
                // window && window.getResultEvent(result);
                // window?.parent?.Gikam?.toast('扫码成功');
                // codeReader.value.reset();
                // codeReader.value.stopContinuousDecode();
                // cid.value = result.text

                // // 发送POST请求给服务器
                // fetch('http://localhost:2303/mtg/parse-product', {
                //     method: 'POST',
                //     headers: {
                //         'Content-Type': 'application/json'
                //     },
                //     body: JSON.stringify({ barcode: result.text })
                // })
                // .then(response => response.json())
                // .then(data => {
                //     // 从服务器获取到产品信息
                //     console.log('产品信息:', data);
                //     // 进行其他操作...
                // })
                // .catch(error => {
                //     console.error('请求出错:', error);
                // });

                // router.push('/scanbook')
            }
        }
    );
};

const cutover = () => {
    if (
        videoInputDevicesArray.value &&
        videoInputDevicesArray.value.length > 1
    ) {
        if (deviceId.value === videoInputDevicesArray.value[0].deviceId) {
            deviceId.value = videoInputDevicesArray.value[1].deviceId;
        } else {
            deviceId.value = videoInputDevicesArray.value[0].deviceId;
        }
    }
    codeReader.value.stopStreams();
};

// 切换摄像头
const toggle = async () => {
    codeReader.value.stopStreams();
    timer = setTimeout(() => {
        timer = null;
    }, 2000);
    if (timer) {
        await codeReader.value.tryPlayVideo('video');
        cutover();
        decodeFromInputVideoFunc();
    }
};

onMounted(() => {
    openScan();
});

onBeforeUnmount(() => {
    codeReader.value.stopContinuousDecode();
    codeReader.value.reset();
});
</script>

样式部分

<style lang="less" scoped>
.code-reader-content {
    .page {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        width: 100%;
        height: 200px;

        #video {
            // height: 100%;
            width: 100%;
            object-fit: fill;
        }
    }

    .scan-box {
        position: absolute;
        left: 50%;
        top: 58%;
        transform: translate(-50%, -90%);
        height: 20%;
        width: 80%;

        .frame {
            position: absolute;
            width: 15px;
            height: 15px;
            border: 3px solid transparent;
        }

        .upper-left {
            top: 0;
            left: 0;
            border-left-color: rgba(66, 133, 244, 1);
            border-top-color: rgba(66, 133, 244, 1);
        }

        .upper-right {
            top: 0;
            right: 0;
            border-right-color: rgba(66, 133, 244, 1);
            border-top-color: rgba(66, 133, 244, 1);
        }

        .lower-right {
            bottom: 0;
            right: 0;
            border-bottom-color: rgba(66, 133, 244, 1);
            border-right-color: rgba(66, 133, 244, 1);
        }

        .lower-left {
            bottom: 0;
            left: 0;
            border-left-color: rgba(66, 133, 244, 1);
            border-bottom-color: rgba(66, 133, 244, 1);
        }

        .pointer-box {
            position: absolute;
            top: 0;
            left: 0;
            width: 98%;
            height: 100%;
            overflow: hidden;

            .pointer {
                height: 3px;
                background-image: linear-gradient(to right,
                        transparent 0%,
                        rgba(66, 133, 244, 1) 50%,
                        transparent 100%);
                transform: translateY(-3px);
                animation: move 2s linear infinite;
            }

            @keyframes move {
                0% {
                    transform: translateY(-3px);
                }

                100% {
                    transform: translateY(calc(20vh - 3px));
                }
            }
        }

        .tip {
            position: absolute;
            left: 50%;
            top: 122%;
            transform: translate(-50%, 0);
            white-space: nowrap;
            color: rgb(176, 209, 28);
            font-size: 16px;
        }

        .btn-switch {
            position: absolute;
            left: 50%;
            top: 140%;
            width: 20px;
            height: 20px;
            transform: translate(-50%, 0);
            background-color: red;
        }

        .btn-wc {
            position: absolute;
            left: 50%;
            top: 160%;
            transform: translate(-50%, 0);
        }
    }
}
</style>

效果图预览

扫描中...                    扫描完

 

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值