在后面一篇文章中我们介绍了使用微信sdk实现扫码功能,这一篇来介绍一下扫码的备选方案-通过html5-qrcode实现扫码
缺点:无法兼容最新鸿蒙系统,部分鸿蒙手机会将二维码方法导致二维码模糊,不自带扫码特效,需自行使用css进行模仿
优点:不依赖任何壳子,调用浏览器的方法打开摄像头
1.调用前置环境准备
// 检查设备是否支持摄像头并检测用户授权状态
const checkDeviceSupportCamera = async () => {
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
uni.$u.toast("当前设备不支持摄像头");
return;
}
try {
// 检查设备是否有摄像头
const devices = await navigator.mediaDevices.enumerateDevices();
const hasCamera = devices.some((device) => device.kind === "videoinput");
if (!hasCamera) {
uni.$u.toast("未检测到摄像头设备");
return;
}
// 检查用户是否允许摄像头权限
const permissionStatus = await navigator.permissions.query({ name: "camera" });
if (permissionStatus.state === "denied") {
// 用户拒绝授权
uni.$u.toast("摄像头权限被拒绝");
return;
} else if (permissionStatus.state === "prompt") {
// 如果权限状态为 "prompt",调用 getUserMedia 触发授权弹窗
// await navigator.mediaDevices.getUserMedia({ video: true });这里如果不注释会导致老版本的鸿蒙系统手机授权后黑屏
}
// 如果用户已授权,跳转到扫码页面
let url = "/pagesB/sancode/index";
uni.navigateTo({
url,
});
} catch (err) {
console.error("检查摄像头设备失败:", err);
uni.$u.toast("无法访问摄像头设备");
}
};
2.摄像头页面
<template>
<view class="homePage">
<!-- <view class="camera_content">
<view class="loop_line"></view>
<view class="video_nav">
<video id="video_nav_id" autoplay :controls="false"></video>
</view>
</view> -->
<div id="video_nav_id"></div>
</view>
</template>
<script>
import { Html5Qrcode } from "html5-qrcode";
export default {
data() {
return {
html5QrCode: null,
};
},
mounted() {
this.html5QrCode = new Html5Qrcode("video_nav_id");
this.startScanning();
},
onUnload() {
this.stopScanning();
},
methods: {
//Error getting userMedia.error =NotReadableError:Could not start videosource
startScanning() {
this.html5QrCode
.start(
{ facingMode: "environment" }, // 使用后置摄像头
{
fps: 10,
aspectRatio: 1.777778, // 可选,视频馈送需要的纵横比,(4:3--1.333334, 16:9--1.777778, 1:1--1.0)传递错误的纵横比会导致视频不显示
},
(decodedText) => {
console.log("扫码结果:", decodedText);
},
(errorMessage) => {
console.warn("扫码失败:", errorMessage);
}
)
.catch((err) => {
console.error("摄像头启动失败:", err);
uni.navigateBack({ delta: 1 });
});
},
stopScanning() {
this.html5QrCode.stop().then(() => {
console.log("摄像头已停止");
});
},
},
};
</script>
<style scoped lang="scss">
.camera_page {
width: 100vw;
display: flex;
flex-direction: column;
height: calc(100vh - env(safe-area-inset-bottom));
}
.camera_content {
height: 100%;
width: 100%;
position: relative;
}
.loop_line {
height: 3px;
width: 80%;
background-color: aliceblue;
border-radius: 50%;
box-shadow: 1px -4px 25px 7px rgba(255, 255, 255, 0.5);
position: absolute;
left: 50%;
top: 20%;
transform: translateX(-50%);
animation: myfirst 3s infinite;
z-index: 99;
}
@keyframes myfirst {
from {
top: 20%;
}
to {
top: 80%;
}
}
.video_nav {
height: 100vh;
width: 100vw;
}
#video_nav_id {
height: 100%;
width: 100%;
}
/deep/.uni-video-cover {
display: none;
}
#video_nav_id {
flex: 1;
width: 100%;
}
</style>