一、需求描述
識(shí)別二維碼圖片中的內(nèi)容
二、尋找工具
首先要找看看有哪些可用的識(shí)別二維碼圖片插件。
問了chatGPT,它給了幾種插件選擇:Zxing-js/library、QuaggaJS、jsQR、react-qr-reader、react-qr-scanner。
但是上面幾種都不適用我的項(xiàng)目,最終選擇了@zxing/browser。
三、實(shí)現(xiàn)方案
以下是基于react16+的項(xiàng)目使用例子
- 首先安裝npm依賴
cnpm i @zxing/browser --save
cnpm i @zxing/library --save
- 封裝方法
import { BrowserQRCodeReader } from '@zxing/browser'
/**
* 解碼二維碼圖片
* @param {*} imageUrl 二維碼圖片url
*/
export const handleDecode = async (imageUrl) => {
const codeReader = new BrowserQRCodeReader()
const img = document.createElement('img')
const base64Str = await imgUrlToBase64(imageUrl)
img.src = base64Str
// 等待圖片加載完成
await new Promise((resolve) => {
img.onload = resolve
})
codeReader.decodeFromImageElement(img).then((result) => {
console.log('二維碼圖片內(nèi)容', result.text)
}).catch((err) => {
console.warn('二維碼圖片解碼失敗了', err)
})
}
/**
* 將圖片轉(zhuǎn)為base64
* @param {*} imgUrl 圖片url
* @returns
*/
const imgUrlToBase64 = (imgUrl) => {
function toBase64(image) {
const canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
const ctx = canvas.getContext('2d')
ctx.drawImage(image, 0, 0, image.width, image.height)
const base64 = canvas.toDataURL('image/png')
return base64
}
return new Promise((resolve, reject) => {
const image = new Image()
image.setAttribute('crossOrigin', 'anonymous') // 解決跨域
image.crossOrigin = '*'
image.src = `${imgUrl}&v=${Math.random()}`// 解決圖片URL緩存問題
image.onload = () => {
resolve(toBase64(image))
}
})
}
- 調(diào)用識(shí)別二維碼圖片方法,傳人圖片url。
const imgUrl = "http://*****"
handleDecode(imgUrl)
- 以上方法使用于已經(jīng)能拿到二維碼url的場景,若二維碼圖片是用本地上傳拿到的等其他形式,可以自己去庫里找對應(yīng)的方法 ??
https://github.com/zxing-js/browser#readme
三、以下是噼里啪啦吐槽一番遇到的坑,可以忽略
- 首先就是找插件的途中,遇到了較多問題,用了chatGPT推薦的幾種插件,發(fā)現(xiàn)都會(huì)報(bào)錯(cuò),有的是兼容問題,有的是使用的時(shí)候,識(shí)別的方法就是報(bào)錯(cuò)了,但是還得看源碼研究它的實(shí)現(xiàn)方法就比較麻煩,果斷換下一個(gè)插件。最后還是zxing比較靠譜,而且還是用了它的衍生插件才成功。
- 插件找到了,但是遇到圖片跨域的問題,這里真的想說chatGPT騙得我好慘,就因?yàn)槲矣玫拿赓M(fèi)版是吧。用了幾種解決方案都不行,還得是谷歌靠譜,最終通過轉(zhuǎn)成base64的方式,才解決了這個(gè)問題,一開始僅僅設(shè)置了crossOrigin是沒有用的。