| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- <template>
- <view class="easy-scancode" v-if="show">
- <view id="reader"></view>
- <!-- 扫码提示区域 -->
- <view class="scan-tip-overlay">
- <view class="scan-tip"> 请将二维码放入框内 </view>
- </view>
- </view>
- </template>
- <script>
- import { Html5Qrcode } from "html5-qrcode";
- export default {
- name: "easy-scancode",
- data() {
- return {
- options: {
- success: () => {},
- fail: () => {},
- },
- show: false,
- html5QrCode: null,
- };
- },
- methods: {
- start(options) {
- this.options = options;
- // #ifdef H5
- // 检查摄像头权限
- if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
- navigator.mediaDevices
- .getUserMedia({
- video: true,
- })
- .then((stream) => {
- // 获得权限后关闭流
- stream.getTracks().forEach((track) => track.stop());
- this.show = true;
- // 有权限后调用扫码
- this.getCameras();
- })
- .catch((err) => {
- // 用户拒绝了权限
- uni.showToast({
- title: "请允许使用摄像头权限!",
- icon: "none",
- });
- this.options.fail("未获得摄像头权限");
- });
- } else {
- uni.showToast({
- title: "您的浏览器不支持访问摄像头",
- icon: "none",
- });
- this.options.fail("浏览器不支持访问摄像头");
- }
- return;
- // #endif
- // 其他环境
- uni.scanCode({
- onlyFromCamera: true,
- success: (res) => {
- this.options.success(res.result, res);
- },
- fail: (rej) => {
- this.options.fail("扫码失败");
- },
- });
- },
- stop() {
- this.show = false;
- let that = this;
- this.html5QrCode
- .stop()
- .then((ignore) => {
- // 二维码扫描已停止
- console.log("二维码扫描已停止");
- })
- .catch((err) => {
- // 停止失败,处理错误
- console.log("无法停止扫描");
- });
- },
- getCameras() {
- let that = this;
- Html5Qrcode.getCameras()
- .then((devices) => {
- // console.log(devices)
- that.html5QrCode = new Html5Qrcode("reader");
- let windowInfo = uni.getWindowInfo();
- console.log(windowInfo);
- const width = windowInfo.windowWidth;
- const height = windowInfo.windowHeight;
- // 横屏
- const aspectRatio = width / height;
- // 竖屏
- const reverseAspectRatio = height / width;
- const mobileAspectRatio =
- reverseAspectRatio > 1.5
- ? reverseAspectRatio + (reverseAspectRatio * 12) / 100
- : reverseAspectRatio;
- if (devices && devices.length) {
- let cameraId = "";
- if (devices.length > 1) {
- cameraId = devices[1].id;
- } else {
- cameraId = devices[0].id;
- }
- // 计算二维码扫描框大小 - 使用宽度/高度中较小的值来确保方框适合屏幕
- // 并在扫描区域周围留出一些边距
- const qrboxSize = Math.min(width, height) * 0.7;
- console.log(qrboxSize);
- // 使用这个来开始扫描
- that.html5QrCode
- .start(
- {
- facingMode: "environment",
- },
- {
- fps: 10, // 可选,二维码扫描的每秒帧数
- aspectRatio: aspectRatio,
- qrbox: { width: qrboxSize, height: qrboxSize }, // 可选,如果你想要边界框UI
- videoConstraints: {
- facingMode: "environment",
- aspectRatio: width < 600 ? mobileAspectRatio : aspectRatio,
- },
- },
- (decodedText, decodedResult) => {
- // 当码被读取时执行操作
- console.log("decodedText", decodedText);
- that.options.success(decodedText, decodedResult);
- that.stop();
- },
- (errorMessage) => {
- // 解析错误,忽略它
- // console.log('解析错误,忽略它', errorMessage)
- }
- )
- .catch((err) => {
- // 启动失败,处理它
- console.log("启动失败,需要处理");
- that.options.fail(err);
- this.show = false;
- });
- }
- })
- .catch((err) => {
- // 处理错误
- console.log(err);
- that.options.fail(err);
- this.show = false;
- });
- },
- },
- };
- </script>
- <style lang="scss" scoped>
- .easy-scancode {
- width: 100vw;
- height: 100vh;
- position: fixed;
- z-index: 1000;
- top: 0;
- left: 0;
- background-color: #000;
- }
- #reader {
- top: 50%;
- left: 0;
- transform: translateY(-50%);
- }
- .scan-tip-overlay {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: 10000;
- pointer-events: none; /* 不阻挡摄像头画面 */
- }
- .scan-tip {
- position: absolute;
- top: 74%;
- left: 50%;
- transform: translateX(-50%);
- color: #fff;
- font-size: 16px;
- text-align: center;
- z-index: 10001;
- background-color: rgba(0, 0, 0, 0.5);
- padding: 10px 20px;
- border-radius: 5px;
- }
- </style>
|