本文主要講述的是采用瀏覽器來識別二維碼 / 條形碼等,并對其解析得到相應的結果。還有一個目的就是為了驗證 iphone 是否無法自動開啟攝像頭進行掃描。需求也非常簡單,就是用 Web 瀏覽器實現二維碼的掃描及解析,我做了個簡單的 Demo 放在 Github 上面,可以體驗一下,若用得上,可下載源碼試試。

Safari 掃描二維碼及解析結果
Vue3 + Vite + Ant-Design-Vue + ZXing,該 Demo 主要的技術及其相應的依賴。對于 Vue3 + Vite 項目的構建,可以自行查看官網教程,至于 Ant-Design-Vue 和 ZXing-JS,需要注意的是 Ant-Design-Vue 的安裝記得加個 @next 版本,其它無異。
# 構建項目后運行
npm init vite-App miitvip-scan-demo
cd miitvip-scan-demo
npm install
npm run dev
# 安裝依賴
npm i ant-design-vue@next --save
npm i @zxing/library --save
Template
video 標簽用于顯示攝像頭內容
<template>
<video class="video" id="video" ref="video" autoplay></video>
</template>

Safari 提示網站需要獲取相機權限
OpenCamera
拉起攝像頭,若獲取不到媒體設備的列表,則簡單的拋出個錯誤提示。
async openCamera() {
this.$message.success({
content: '正在嘗試拉起攝像頭 ...',
duration: 0
})
if (!navigator.mediaDevices) {
this.$message.destroy()
this.iphone = true
this.$message.success({
content: 'iPhone 其它瀏覽器無權限自動開啟攝像頭 ...',
duration: 0
})
} else {
this.reader.listVideoInputDevices().then((devices) => {
this.decode(devices[0].deviceId)
}).catch((err) => {
this.errMsg = err
this.$message.destroy()
this.$message.error({
content: err,
duration: 0
})
})
}
}

拉起攝像頭,進入掃描狀態
Decode
decode 解析內容,這里采用的是單次解析,即掃描成功后需要重新刷新一下頁面方可再次進行識別操作,若要多次掃描,可用 decodeFromInputVideoDeviceContinuously 方法去識別。
decode(id: any) {
this.reader.reset()
this.$message.destroy()
this.$message.success({
content: '正在嘗試識別,請對準攝像頭 ...',
duration: 0
})
this.reader.decodeOnceFromVideoDevice(id, 'video').then((res) => {
this.$message.destroy()
this.content = res.text
this.time = new Date(res.timestamp)
this.modalVisible = true
}).catch((err) => {
this.$message.destroy()
this.$message.error({
content: '識別失敗,請刷新后再次嘗試 ...',
duration: 0
})
this.errMsg = err
})
}

非 Safari 瀏覽器無權自動拉起相機 - iPhone
總結
https://github.com/lirongtong/miitvip-scan-demo
https://scan.makeit.vip/
最后的結果就是:iPhone 中,除了自帶的 Safari 瀏覽器外,其它任何的瀏覽器,都無法自動拉起相機,沒有這個權限,但是我們可以采用折中的方式,即用拍照的形式來進行識別,可以用如下的代碼語句來拉起攝像頭,拍照后識別照片內容,我在 Demo 上也做了,但是識別的效果卻是不如攝像頭實時掃描的好,正確率很低,常常識別失敗(上述兩個地址分別為 Github 與 Demo 地址)。
<input class="file" type="file" ref="camera" capture="camera" accept="image/*" @change="change" />

拍照的也能識別,但正確率比較低