jsQr解决uniapp H5环境图片二维码识别问题
- 下载jsqr
npm install jsqr -s
- 获取图片信息并使用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 };
- 页面中使用
<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执行慢,耗费性能的问题
- 新建一个文件去加载执行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);
};
- 使用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);
});
};