Vue3掃描二維碼

<template>
<form>
    <div class="form-group">
        <label>選擇攝像頭</label>
        <select class="form-control" v-model="currentDevices">
            <template v-if="videoInputDevices.length > 0">
                <option v-for="item, index in videoInputDevices" :key="index" :value="item.value">{{ item.label }}</option>
            </template>
        </select>
    </div>
    <div class="form-group">
        <label>掃描結果</label>
        <input v-model="codeStr" type="text" class="form-control">
    </div>
    <button type="button" class="btn btn-primary" @click="scanStart" >打開掃描</button>
</form>

<!-- Modal -->
<div class="modal fade" id="scanModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">掃描二維碼</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <!-- 掃描框 -->
        <video id="video" width="400" height="200">
            {{ currentDevices.label }}
        </video>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" @click="scanCancel">關閉</button>
      </div>
    </div>
  </div>
</div>
</template>

<script >
import { defineComponent, ref, onBeforeMount, onBeforeUnmount } from "vue";
import { BrowserMultiFormatReader } from '@zxing/library'
import { swal2 } from "./common";

export default defineComponent({
  name: "ScanVue",
  setup(){
    const codeStr = ref('')
    const codeReader = new BrowserMultiFormatReader()
    // 所有視頻輸入設備
    const videoInputDevices = ref([])
    // 當前輸入設備
    const currentDevices = ref(null)
    // 查找攝像頭
    async function deviceDetect(){
        await codeReader.listVideoInputDevices().then((devices) => {
            if(devices.length > 0){
                videoInputDevices.value = []
                // 攝像頭倒敘:後置攝像頭優先,默認順序:前置,後置
                devices.reverse()
                swal2.success("攝像頭檢測成功")
                videoInputDevices.value.push({label:'後置攝像頭',value:devices[0]})
                if(devices.length > 1){
                    videoInputDevices.value.push({label:'前置攝像頭',value:devices[1]})
                }
                // 默認選擇後置
                currentDevices.value = devices[0]
            }
        })
        .catch((err) => {swal2.error(`${err}`)})
    }
    /**
     * 掃描回調函數
     * @param {any} data 掃描結果,沒有結果爲null
     */
    function decodeCallback(data){
        if(data != null){ codeStr.value = data;scanCancel()}
    }
    // 解碼
    function decodeFromInputVideo(){
        // 重置攝像頭
        codeReader.reset()
        // currentDevices.value.deviceId 當前設備ID
        // deviceId: string, videoSource: string | HTMLVideoElement
        // let cam = videoInputDevices.value[0]
        codeReader.decodeFromVideoDevice(currentDevices.value.deviceId, "video", decodeCallback).then((value, err) => {
            // 結果字符串
            if(value != undefined){
                // 解碼成功後關閉攝像頭
                codeReader.reset()
            }
            if(err){ swal2.error(`${err}`)}
        })
        .catch((err) => {swal2.error(`${err}`)})
    }

    function scanStart(){
        $('#scanModal').modal('toggle')
        decodeFromInputVideo()
    }

    function scanCancel(){
        codeReader.reset()
        $('#scanModal').modal('toggle')
    }

    onBeforeMount(() =>{
        deviceDetect()
    })

    onBeforeUnmount(() =>{
        codeReader.reset()
    })

    return {
        videoInputDevices, scanStart, scanCancel, codeStr, currentDevices
    }
  }
  
})
</script>

<style scoped>

</style>

edge 瀏覽器啓用: Allow invalid certificates for resources loaded from localhost. Insecure origins treated as secure

vue.config.js

devServer:{
    host:'0.0.0.0',
    port: 4000,
    allowedHosts: ['.host.cn', 'host.cn'],
  }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章