uniapp 使用jsQR识别二维码

371 阅读1分钟

1. 安装jsqr

npm install jsqr --save

2. 导入jsqr

import jsQR from 'jsqr';

3. 添加组件

<template>
    <view>
        <canvas :style="{width: screenWidth+'px', height: screenHeight+'px',position: 'absolute', top: 999999, left: 999999, zIndex: -20, opacity: 0}" canvas-id="qrcodeCanvas" id="qrcodeCanvas"></canvas>
        <u-upload class="uUpload" :file-list="fileList" :before-upload="beforeUpload" ></u-upload>
    </view>
</template>

4. 完整代码

<script>
	import jsQR from 'jsqr';

	export default {
		name: 'UploadFile',
		data() {
			return {
				fileList: [], //图片列表
				canvasContext: null, // Canvas 的上下文对象
				screenWidth: 300,
				screenHeight: 300,
			};
		},
		mounted() {
			this.screenWidth = uni.getSystemInfoSync().screenWidth
			this.screenHeight = uni.getSystemInfoSync().screenHeight
		},
		methods: {
			async beforeUpload(index, list) {
				if (list.length > 0) {
					uni.showLoading({
						title: "识别二维码中...",
						mask: true,
					});
                                  // 1. 获取图片本地路径
					const file = list[index].file; // 获取图片路径
                                  // 2. 解码
					return this.decodeQrCode(file).then((result) => {
						if (result.data) {
                                                  // 解码成功
                                                  // 其他操作
                                                  // ***********
                                                  return true;
						} else {
							return false;
						}
                                          uni.hideLoading()
					}).catch((error) => {
						// this.$toast.msg(error.msg || '二维码检查失败');
                                          uni.hideLoading()
						return false;
					});
					// #endif
				}
			},

			resizeCanvas(canvas, imageWidth, imageHeight) {
				// 计算缩放比例
				let scale = Math.min(this.screenWidth / imageWidth, this.screenHeight / imageHeight);
				
				return {
					drawWidth: imageWidth * scale,
					drawHeight: imageHeight * scale,
				}
			},

			

			async decodeQrCode(myfile) {
                            try {
                        return new Promise((resolve, reject) => {
                            // 2.1 获取图片宽高
                            uni.getImageInfo({
                                src: myfile.path,
                                success: (image) => {
                                // console.log(image.width);
                                // console.log(image.height);
                                // console.log(myfile.path, 'file');

                                var context = uni.createCanvasContext('qrcodeCanvas')
                                const {drawWidth, drawHeight} = this.resizeCanvas(context, image.width, image.height)
                                // 2.2 canvas 绘制图片
                                // canvas宽高设置为 屏幕的宽高,二维码 按原图比例缩放为 屏幕的宽高
                                context.drawImage(myfile.path, 0, 0, drawWidth, drawHeight); // (图片源, x, y, 宽度, 高度)
                                context.draw(false, () => {
                                    // 必须延迟绘制
                                    setTimeout(() => {
                                            console.log('绘制完成');
                                            // 2.3 图片转 Uint8ClampedArray
                                            uni.canvasGetImageData({
                                            canvasId: 'qrcodeCanvas',
                                            x: 0,
                                            y: 0,
                                            width: this.screenWidth, // 宽度为canvas的宽
                                            height: this.screenHeight, // 高度为canvas的高
                                            success: (res) => {
                                                try{
                                                    // 2.4 解码二维码,解码图片的宽高为canvas宽高,保证 解码图像像素点数据完整,否则 识别二维码失败
                                                    this.detectQRCodeJSQR(res.data, this.screenWidth, this.screenHeight).then(res=> {
                                                            // console.log(res);
                                                            resolve({
                                                                    data: true,
                                                                    msg: res
                                                            })
                                                    }).catch(error => {
                                                            console.log(error);
                                                            reject({
                                                                    data: false,
                                                                    msg: error
                                                            })
                                                    })
                                                }catch(e){
                                                    //TODO handle the exception
                                                    console.log(e, '捕获格式错误');
                                                }
                                                }
                                        })
                                }, 0)
                            })
                        }
                    });
                })
                } catch (e) {
                        //TODO handle the exception
                        console.log(e, 'error');
                }
            },

            // ************检查二维码************
            async detectQRCodeJSQR(imageData, width, height) {
                    return new Promise((resolve, reject)=> {
                            if (!imageData instanceof Uint8ClampedArray) {
                                    console.error('Invalid image data');
                                    return;
                            }
                            console.log(imageData);
                            // 3. 调用jsQR 进行二维码识别
                            const code = jsQR(imageData, width, height, {
                                    inversionAttempts: "attemptBoth"
                            });
                            if (code) {
                                    console.log('识别到的二维码内容:', code.data);
                                    resolve({
                                            data: true,
                                            msg: code.data
                                    });
                            } else {
                                    console.log('未识别到二维码');
                                    reject({
                                            data: false,
                                            msg: '请上传有效二维码'
                                    });
                            }
                    })
            },

		},
	}
</script>