一、 卡顿问题
在uniapp中,由于需要进行实时扫码,使用了小程序的camera组件。camera需要用户授权,因此直接显示会导致空白问题。而同时在页面切换时,可能由于camera本身比较复杂,页面切换过程中非常卡顿,于是尝试通过v-if进行解决。如下:
<view v-if="loaded && cameraEnable">
<camera device-position="back" flash="off" mode="scanCode" @error="error"
style="width: 100%; height: 30vh" @scancode="onScanCode"></camera>
</view>
<view v-else>
<view class="flex-col flex-center" style="height: 30vh;" v-else>
<view style="margin: 10rpx 0;">相机不可用</view>
<view>
<u-button type="primary" size="mini" @click="getCameraAuth">授权</u-button>
</view>
</view>
</view>
<script>
export default {
data() {
return {
loaded: false,
cameraEnable: true,
// 防止mounted与onShow冲突
loop: false
};
},
onShow() {
if (this.loaded && !this.loop){
// 轮询当前相机权限状态,当用户授权则将cameraEnable设置为true
this.loopGetCameraInfo();
}
},
mounted() {
setTimeout(() => {
this.loaded = true;
this.loopGetCameraInfo();
}, 1000);
}
}
</script>
通过延迟一秒钟进行camera的显示解决了卡顿问题。
同时需求需要进入页面就弹出授权框,因此在mounted中的setTimeout回调调用后,loaded和cameraEnable都是true相机会显示一下,系统第一次会自动弹出权限框,然后通过loopGetCameraInfo方法查询相机状态,若当前无权限则隐藏。
二、 授权后无法显示相机
如果上述v-if改为通过v-show进行显示隐藏,则当用户通过手动授权后,相机会白屏。只有通过v-if对dom元素的删除插入才能刷新camera的状态。所以使用上面的写法就好了。
三、 ios端报错can insert only one camera
如果使用v-if来进行显隐,则在ios上会出现该问题。因此如果需要兼容ios端,我们这边的解决办法是将获取权限提前到前面的页面中。
四、 手动授权
我们不使用系统的授权而通过手动授权的方式,即一进入页面弹出授权框给用户点击,而当用户拒绝则显示授权按钮给用户点击触发。而这种方案需要将cameraEnable初始值设置为false。这样可以解决上述所有问题。授权方法为下面的getCameraAuth
相关代码
loopGetCameraInfo () {
this.loop = true;
this.getCameraAuthInfo();
setTimeout(() => {
if (!this.loaded) {
this.loopGetCameraInfo();
} else {
if (!this.cameraEnable) {
this.loopGetCameraInfo();
} else {
this.loop = false;
}
}
}, 500);
},
getCameraAuthInfo() {
const that = this;
uni.getSetting({
success(res) {
const authSetting = res.authSetting;
if (authSetting['scope.camera']) {
// 已经授权
that.cameraEnable = true;
} else {
that.cameraEnable = false;
}
}
});
},
// 手动授权
getCameraAuth() {
const that = this;
// 获取摄像头权限
uni.getSetting({
success(res) {
console.log("auth res", JSON.stringify(res));
const authSetting = res.authSetting;
if (authSetting['scope.camera']) {
// 已经授权
that.cameraEnable = true;
} else {
// 未授权
uni.authorize({
scope: 'scope.camera',
success(resSuccess) {
// 同意授权
that.cameraEnable = true;
},
fail(resFail) {
// 引导用户授权
uni.showModal({
title: '授权',
content: '需要您授权获取摄像头权限',
success: function(res) {
if (res.confirm) {
uni.openSetting({
success(resOpenSetting) {
// resOpenSetting: {errMsg: "openSetting:ok", authSetting: {scope.camera: false}}
console.log("resOpenSetting: ",
resOpenSetting)
const authSetting =
resOpenSetting.authSetting
if (authSetting && authSetting[
'scope.camera']) {
that.getCameraAuthInfo();
} else {
uni.showToast({
icon: 'none',
title: '您拒绝授权小程序获取摄像头权限',
duration: 1500
});
}
}
});
} else if (res.cancel) {
uni.showToast({
icon: 'none',
title: '您拒绝授权小程序获取摄像头权限',
duration: 1500
});
}
}
});
}
});
}
}
});
}