解决uniapp在H5环境下图片二维码识别问题

jsQr解决uniapp H5环境图片二维码识别问题

  1. 下载jsqr
npm install jsqr -s
  1. 获取图片信息并使用jsqr解析图片中的二维码
import jsQR from 'jsqr';

/**
 * 从相册中选择图片
 * @param {Object} [options] - 选择图片的配置选项
 * @param {number} [options.count=1] - 最多可以选择的图片数量
 * @param {string[]} [options.sourceType=["album"]] - 图片的来源,可选值为 'album' 相册、'camera' 相机
 * @returns {Promise<string|false>} - 返回选择的图片文件路径或者 false(选择失败)
 */
const chooseImage = (options = {}) => {
    const { count = 1, sourceType = ["album"] } = options;
    return new Promise((resolve, reject) => {
        uni.chooseImage({
            count,
            sourceType,
            success(res) {
                resolve(res.tempFilePaths[0]);
            },
            fail(err) {
                resolve(false);
            },
        });
    });
};

/**
 * 获取图片信息,包括宽度、高度等
 * @param {Object} [options] - 获取图片信息的配置选项
 * @param {string} [options.filePath] - 图片文件路径,如果未提供则调用 chooseImage 选择图片
 * @returns {Promise<Object|false>} - 返回包含图片信息的对象或者 false(获取失败)
 */
const getImageInfo = async (options = {}) => {
    let { filePath } = options;

    if (!filePath) {
        filePath = await chooseImage();
    }

    if (!filePath) {
        return false;
    }

    return new Promise((resolve, reject) => {
        uni.getImageInfo({
            src: filePath,
            success(res) {
                resolve(res);
            },
            fail(err) {
                resolve(false);
            },
        });
    });
};

/**
 * 解析图片中的 QR 码
 * @returns {Promise<string|false>} - 返回解析出的 QR 码数据或者 false(解析失败)
 */
const decodeQRCode = async () => {
    return new Promise(async (resolve, reject) => {
        // 获取选择的图片信息,调用 getImageInfo 函数
        const imgFile = await getImageInfo();

        // 如果成功获取到图片信息
        if (imgFile) {
            const { width, height, path } = imgFile;

            // 创建一个新的 Image 对象
            const img = new Image();

            // 当图片加载完成后执行以下操作
            img.onload = () => {
                // 创建一个新的 Canvas 元素
                const canvas = document.createElement("canvas");
                canvas.width = width;
                canvas.height = height;

                // 获取 Canvas 的 2D 上下文
                const ctx = canvas.getContext("2d");

                // 将图片绘制到 Canvas 上
                ctx.drawImage(img, 0, 0, width, height);

                // 获取绘制的图片数据
                const imageData = ctx.getImageData(0, 0, width, height);

                const code = jsQR(imageData.data, imageData.width, imageData.height); // 使用jsQR解析二维码
                if (code) {
                  resolve(code.data); // 解析成功返回二维码内容
                } else {
                  uni.showToast({
                    title: "无法识别此图片",
                    duration: 2000,
                    icon: "none",
                  });
                  resolve(false); // 解析失败返回false
                }
             
            };

            // 设置 Image 对象的 src 属性,开始加载图片
            img.src = path;

            return; // 结束函数执行,等待异步操作完成后 resolve 结果
        }

        // 如果未能获取图片信息,直接返回 false
        resolve(false);
    });
};

export { chooseImage, getImageInfo, decodeQRCode };

  1. 页面中使用
<template>
  <view>
    <button @click="handle">上传图片</button>
  </view>
</template>

<script setup>
import { decodeQRCode } from "@/utils";
const handle = async () => {
  const res = await decodeQRCode();
  if (res) {
    console.log(res);
  }
};
</script>

在这里插入图片描述

可优化的模块
如果jsqr执行比较慢的话可以 采用webworker去开一个线程解决jsqr执行慢,耗费性能的问题

  1. 新建一个文件去加载执行jsqr
    webWorkers/jsQRWoker.js
    在这里插入图片描述
import jsQR from 'jsqr';

self.onmessage = function (e) {
    const { imageData, width, height } = e.data;
    const code = jsQR(imageData, width, height);
    self.postMessage(code);
};
  1. 使用web worker调用jsqr
    基于上面的部分修改一下decodeQRCode方法
/**
 * 解析图片中的 QR 码
 * @returns {Promise<string|false>} - 返回解析出的 QR 码数据或者 false(解析失败)
 */
const decodeQRCode = async () => {
    return new Promise(async (resolve, reject) => {
        // 获取选择的图片信息,调用 getImageInfo 函数
        const imgFile = await getImageInfo();

        // 如果成功获取到图片信息
        if (imgFile) {
            const { width, height, path } = imgFile;

            // 创建一个新的 Image 对象
            const img = new Image();

            // 当图片加载完成后执行以下操作
            img.onload = () => {
                // 创建一个新的 Canvas 元素
                const canvas = document.createElement("canvas");
                canvas.width = width;
                canvas.height = height;

                // 获取 Canvas 的 2D 上下文
                const ctx = canvas.getContext("2d");

                // 将图片绘制到 Canvas 上
                ctx.drawImage(img, 0, 0, width, height);

                // 获取绘制的图片数据
                const imageData = ctx.getImageData(0, 0, width, height);

                // 直接使用jsqr -------------star--------------------------------
                // const code = jsQR(imageData.data, imageData.width, imageData.height); // 使用jsQR解析二维码
                // if (code) {
                //     resolve(code.data); // 解析成功返回二维码内容
                // } else {
                //     uni.showToast({
                //         title: "无法识别此图片",
                //         duration: 2000,
                //         icon: "none",
                //     });
                //     resolve(false); // 解析失败返回false
                // }
                // 直接使用jsqr -------------end--------------------------------

                // 使用 web worker ---------star--------------------------------
                // 创建一个新的 web worker 对象,用于后台处理解析 QR 码
                const worker = new Worker(
                    new URL("./webWorkers/jsQRWorker.js", import.meta.url),
                    {
                        type: "module",
                    }
                );

                // 向 worker 发送图片数据和尺寸信息
                worker.postMessage({ imageData: imageData.data, width, height });

                // 监听 worker 返回的消息
                worker.onmessage = function (e) {
                    const code = e.data;
                    // worker 比较耗费资源 使用完毕之后关闭
                    worker.terminate();
                    // 如果成功解析出 QR 码
                    if (code) {
                        resolve(code.data); // 解析结果作为 Promise 的结果返回
                    } else {
                        // 如果无法识别出 QR 码,显示提示信息
                        uni.showToast({
                            title: "无法识别此图片",
                            duration: 1500,
                            icon: "none",
                        });
                        resolve(false); // 解析失败,返回 false
                    }
                };
                // 使用 web worker ---------end--------------------------------

            };

            // 设置 Image 对象的 src 属性,开始加载图片
            img.src = path;

            return; // 结束函数执行,等待异步操作完成后 resolve 结果
        }

        // 如果未能获取图片信息,直接返回 false
        resolve(false);
    });
};
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值