Vue实现长按图片识别图中二维码
思路:要想实现可以识别图片中的二维码,那必定是要将这张图进行上传操作,上传则需要file对象格式。不管是在H5还是APP中,展示的图片都是通过url的方式展示在img标签中的,所以大致的思路就是长按图片,获取图片url,并将url转换成可实现上传操作的file对象格式,再通过某个插件对上传的file进行是否存在QR码的识别判断操作,从而实现了长按识别二维码,思路成立,开始实现。
1. 首先我们需要实现长按某张图片,几百毫秒后执行下一步操作,这一步就包括了获取这张图片url,这一步可以通过@touchstart结合setTimeout实现。
// 标签中
<div class="image-preview" @touchstart="holdDown"></div>
holdDown (e) {
setTimeout(() => {
if(e.target.nodeName === 'IMG'){
this.showSheet = true
this.imgUrl = e.target.currentSrc
this.urlToFile(url)
}
},500)
}
2. 我们需要封装一个可以将url的图片地址转换成可上传的file对象格式,这里就是整个实现代码的核心。
urlToFile (url, callback) {
const image = new Image()
image.crossOrigin = '*'
image.src = url
image.onload = function () {
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 ext = image.src.substring(image.src.lastIndexOf('.') + 1).toLowerCase()
const dataURL = canvas.toDataURL('image/' + ext)
const type = 'image/' + ext
const bytes = window.atob(dataURL.split(',')[1])
const ab = new ArrayBuffer(bytes.length)
const ia = new Uint8Array(ab)
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i)
}
const tempBlob = new Blob([ia], { type: type })
const blob = tempBlob
var file = new File([blob], 'filename', { type: type, lastModified: Date.now() })
callback(file)
}
}
3. 还记得之前传入url的那个方法吗?我们回到长按方法holdDown方法中,再获取callback的file值。
holdDown (e) {
setTimeout(() => {
.
.
.
this.urlToFile(url, (file) => {
console.log(file)
})
}
},500)
}
4. 市面上扫描图片文件二维码的插件并不多,甚至有大神手写了一个reqrcode.js,但不适用于vue。这里我推荐qrcode-decoder插件,他可以通过传入的file实现对图片文件的扫描,识别是否存在二维码,并获取到二维码的内容。
下载方式:
npm install qrcode-decoder
npm install qrcode-decoder --registry=https://registry.npm.taobao.org
5. qrcode-decoder的使用方法
import QrCode from 'qrcode-decoder'
identifyQR (file) {
const url = window.webkitURL.createObjectURL(file)
console.log(url)
const qr = new QrCode()
return qr.decodeFromImage(url)
}
6. 再回到我们获取到file处,使用这个方法,并进行后续操作
holdDown (e) {
setTimeout(() => {
.
.
.
this.urlToFile(url, (file) => {
this.identifyQR(file).then(r => {
if(r.data){
...
}else{
console.log('不是二维码')
}
})
})
}
},500)
}
至此,成功实现了长按识别二维码
总结:方法是自己摸索的,明明可以app解决的问题非要交给前端,不过解决思路还是很清晰的,如果有更好的方法,不妨交流交流。
感谢阅读~
|