项目背景:内嵌至app内的vue-cli+vant2项目
需求:调用手机相机,开启闪光灯、扫描二维码功能
所使用插件/文档:点击: [Vue Qrcode Reader](Decode by Upload | Vue Qrcode Reader (gruhn.github.io))
注意:因为安全原因相机只有在本地http://localhost 或者 https协议下才可以调用,http协议是调不起来。
该插件目前暂不支持条形码,如果你看到这篇文章时,已经支持,记得回来踢我
如何使用
1、下载插件
npm i vue-qrcode-reader
2、引入页面
<qrcode-stream @decode="onDecode" @init="onInit" :torch="torchActive" class="qrcode_stream">
</qrcode-stream>
<qrcode-capture @decode="onDecode" :capture="false" id="ischange" />
import { QrcodeStream, QrcodeCapture } from 'vue-qrcode-reader'
QrcodeStream
直接调用相机实时扫描二维码
@decode
拿到扫描结果的回调
@init
初始化摄像流,主要检验当前设备是否支持相机功能
torch
控制闪光灯的开/关
QrcodeCapture
选择设备本地的图片进行二维码扫描或者拍照进行扫描
capture
'environment'/后置摄像头 'user'/前置摄像头 false/选择文件
我在项目中使用时,无法进行拍照扫描,拍照扫描没有任何返回结果或者报错,不知道到咋回事
我在项目中的使用
<template>
<div>
<div class="sancer_cls">
<qrcode-stream :camera="camera" @decode="onDecode" @init="onInit" :torch="torchActive" class="qrcode_stream">
<div class="header">
<img @click="goback" src="@/assets/imgs/back-black.png" alt="">
</div>
<p class="sancer_msg"> {{ error }} </p>
<van-overlay :show="toLoading"/>
<van-loading v-show="toLoading" class="loading_bg" color="#303030" size="24px"/>
<img src="@/assets/imgs/QR_frame.png" class="scan_frame" alt="扫码框">
<div class="stream_btn">
<div class="btn_content" @click="importNumber">
<img src="@/assets/imgs/importNum.png" class="btn_img" alt="输入编码"/>
<p class="content_p">输入编码</p>
</div>
<div class="btn_content" @click="torchActiveChange">
<img src="@/assets/imgs/switchLight.png" class="btn_img" alt="轻触照亮"/>
<p class="content_p">轻触照亮</p>
</div>
<div class="btn_content" @click="changeI">// 为了支持拍照扫码与使用本地图片扫码功能
<qrcode-capture @decode="onDecode" :capture="selected" id="ischange" style="display:none"/>
<img src="@/assets/imgs/changeImg.png" class="btn_img" alt="选择图片"/>
<p class="content_p">选择图片</p>
</div>
</div>
<button v-if="showRegainCamera" @click="regainCamera" class="regain_camera">重新获取摄像头权限</button>
</qrcode-stream>
</div>
</div>
</template>
<script>
import { QrcodeStream, QrcodeCapture } from 'vue-qrcode-reader'
export default {
components: {
QrcodeStream,
QrcodeCapture,
},
data () {
return {
result: '',
error: '',
torchActive: false,
selected: false, // 值:'environment'/后置摄像头 'user'/前置摄像头 false/选择文件
toLoading: false, //
camera: 'auto', // 原本有缓存导致不能连续扫描同一个二维码,当更改摄影机道具时,此缓存将重置。可以利用这一点连续多次扫描相同的二维码。
showRegainCamera: false, // 重新获取摄像头权限按钮展示控制
}
},
watch:{ },
created(){ },
mounted(){ },
methods: {
async onInit(promise) { // 每次修改 camera 的值 都会重新获取一个新的摄像机流,因此会再次触发 onInit 事件
try {
let r = await promise
console.log(r,'initpromise');
} catch (error) {
if (error.name === 'NotAllowedError') {
this.error = "您需要授予相机访问权限"
this.showRegainCamera = true
} else if (error.name === 'NotFoundError') {
this.error = "这个设备上没有摄像头"
} else if (error.name === 'NotSupportedError') {
this.error = "所需的安全上下文(HTTPS、本地主机)"
} else if (error.name === 'NotReadableError') {
this.error = "相机被占用"
} else if (error.name === 'OverconstrainedError') {
this.error = "摄像头不适用"
} else if (error.name === 'StreamApiNotSupportedError') {
this.error = " 不支持流API"
} else if (error.name === 'InsecureContextError') {
this.error = `请使用HTTPS或localhost使用摄像头`;
} else {
// this.error = `ERROR: Camera error (${error.name})`;
this.showRegainCamera = false
}
} finally {
}
},
async onDecode(res) { // 拿到扫描结果
console.log(res,'------扫描结果');
let self = this
// 自己项目的业务逻辑
this.pause()
await this.timeout(500)
this.unpause()
},
async regainCamera(){ // 重新获取摄像头权限,修改了camera的值会重新出发init
console.log('重新获取摄像头权限');
this.pause()
await this.timeout(500)
this.unpause()
// console.log(this.camera,'==cameracamer');
},
async torchActiveChange(){ // 开/关闪光灯
let self = this
self.torchActive = !self.torchActive
this.pause()
await this.timeout(500)
this.unpause()
},
changeI(){ // 选择图片,触发扫码组件的方法
console.log('选择图片,changeImg');
document.getElementById('ischange').click()
},
unpause () { // 控制摄像流的切换
this.camera = 'auto'
},
pause () { // 控制摄像流的切换
this.camera = 'off'
},
timeout (ms) { // 控制摄像流的切换
return new Promise(resolve => {
window.setTimeout(resolve, ms)
})
},
}
}
</script>
因为安全原因相机只有在本地http://localhost 环境 或者 https环境才可以调用,http是调用不起来。
大家测试的时候记得看一下自己的环境对不对
功能测试方式
1、更改本地运行协议为https方法
vue-clli项目,在vue.config.js中配置
// 使用webpack搭建的项目如何配置暂不知,有知道的小伙伴可以评论一下哦~
devServer:{
https:true
}
再次运行项目即可
2、在手机上运行本地项目
项目运行起来之后如果电脑有相机功能应该可以直接测试(我没用过,但是应该可以)
如果电脑不行,使用手机,项目运行起来之后如上图,会有两个本地项目地址,在手机上输入第二个地址即可测试
达成 支持摄像&只能在本地或者https协议下调用 的条件
手机上测试可以装vconsole来查看控制台
——————————————————总结的分割线———————————————————
Vue Qrcode Reader插件总体就这些了,除了拍照扫描二维码没有满足需求,其他都没问题。
拍照扫描二维码的场景其实很少,跟产品商量看可不可以直接砍掉(●ˇ∀ˇ●)
另外在ios上并没有使用过,可能有无法预见的错误,大家可以参考官方文档来进行使用
点击: [Vue Qrcode Reader](Decode by Upload | Vue Qrcode Reader (gruhn.github.io))