vue实现二维码生成器和解码器

news2025/4/16 21:24:57

vue实现二维码生成器和解码器

1.生成基本二维码:根据输入的value生成二维码。
2.可定制尺寸:通过size调整大小。
3.颜色和背景色:设置二维码颜色和背景。
4.静区(quiet zone)支持:通过quietZone调整周围的空白区域。
5.错误纠正级别:ecl参数控制容错级别。
6.渐变效果:启用线性渐变,可以自定义方向和颜色。
7.Logo嵌入:在二维码中间添加logo,可调整大小、边距、背景色和圆角。
8.错误处理:生成失败时显示错误信息。
9.响应式更新:当props变化时自动重新生成二维码。
10.视图框调整:根据静区计算viewBox,确保正确显示。

效果图:
在这里插入图片描述

step1: 添加依赖 npm install qrcode @types/qrcode

step2:核心组件 实现二维码
C:\Users\wangrusheng\PycharmProjects\untitled3\src\views\QrCode.vue

<template>
  <!-- SVG 容器 -->
  <svg
    v-if="!error"
    :viewBox="viewBox"
    :width="size"
    :height="size"
  >
    <!-- 背景 -->
    <rect
      :x="-quietZone"
      :y="-quietZone"
      :width="size + quietZone * 2"
      :height="size + quietZone * 2"
      :fill="backgroundColor"
    />

    <!-- 渐变定义 -->
    <defs v-if="enableLinearGradient">
      <linearGradient
        id="grad"
        :x1="gradientDirection[0]"
        :y1="gradientDirection[1]"
        :x2="gradientDirection[2]"
        :y2="gradientDirection[3]"
      >
        <stop offset="0" :stop-color="linearGradient[0]" stop-opacity="1"/>
        <stop offset="1" :stop-color="linearGradient[1]" stop-opacity="1"/>
      </linearGradient>
    </defs>

    <!-- 二维码路径 -->
    <path
      :d="path"
      stroke-linecap="butt"
      :stroke="enableLinearGradient ? 'url(#grad)' : color"
      :stroke-width="cellSize"
    />

    <!-- Logo 容器 -->
    <svg
      v-if="logo"
      :x="(size - logoSize - logoMargin * 2) / 2"
      :y="(size - logoSize - logoMargin * 2) / 2"
    >
      <!-- Logo 背景 -->
      <rect
        :width="logoSize + logoMargin * 2"
        :height="logoSize + logoMargin * 2"
        :fill="logoBackgroundColor"
        :rx="logoBorderRadius + (logoMargin / logoSize) * logoBorderRadius"
        :ry="logoBorderRadius + (logoMargin / logoSize) * logoBorderRadius"
      />

      <!-- Logo 图片 -->
      <image
        :x="logoMargin"
        :y="logoMargin"
        :width="logoSize"
        :height="logoSize"
        :href="logo"
        preserveAspectRatio="xMidYMid slice"
        :rx="logoBorderRadius"
        :ry="logoBorderRadius"
      />
    </svg>
  </svg>

  <!-- 错误显示 -->
  <div v-if="error" class="error">
    {{ error.message }}
  </div>
</template>

<script setup lang="ts">
import { ref, watchEffect, computed } from 'vue'
import QRCode from 'qrcode'

// Props 定义
const props = defineProps({
  value: { type: String, default: 'this is a QR code' },
  size: { type: Number, default: 100 },
  color: { type: String, default: 'black' },
  backgroundColor: { type: String, default: 'white' },
  logo: { type: String, default: undefined },
  logoSize: { type: Number, default: 100 * 0.2 }, // 默认基于 size 计算
  logoBackgroundColor: { type: String, default: 'transparent' },
  logoMargin: { type: Number, default: 2 },
  logoBorderRadius: { type: Number, default: 0 },
  quietZone: { type: Number, default: 0 },
  enableLinearGradient: { type: Boolean, default: false },
  gradientDirection: {
    type: Array as () => string[],
    default: () => ['0%', '0%', '100%', '100%']
  },
  linearGradient: {
    type: Array as () => string[],
    default: () => ['rgb(255,0,0)', 'rgb(0,255,255)']
  },
  ecl: { type: String as () => 'L'|'M'|'Q'|'H', default: 'M' }
})

// 响应式数据
const path = ref('')
const cellSize = ref(0)
const error = ref<Error | null>(null)

// 生成二维码矩阵
const genMatrix = (value: string, errorCorrectionLevel: string): boolean[][] => {
  const arr = Array.prototype.slice.call(
    QRCode.create(value, { errorCorrectionLevel }).modules.data, 0
  )
  const sqrt = Math.sqrt(arr.length)
  return arr.reduce((rows: boolean[][], key: boolean, index: number) => {
    (index % sqrt === 0) ? rows.push([key]) : rows[rows.length - 1].push(key)
    return rows
  }, [])
}

// 转换矩阵为 SVG 路径
const transformMatrixIntoPath = (matrix: boolean[][], size: number) => {
  const cellSize = size / matrix.length
  let path = ''
  matrix.forEach((row, i) => {
    let needDraw = false
    row.forEach((column, j) => {
      if (column) {
        if (!needDraw) {
          path += `M${cellSize * j} ${cellSize / 2 + cellSize * i} `
          needDraw = true
        }
        if (needDraw && j === matrix.length - 1) {
          path += `L${cellSize * (j + 1)} ${cellSize / 2 + cellSize * i} `
        }
      } else {
        if (needDraw) {
          path += `L${cellSize * j} ${cellSize / 2 + cellSize * i} `
          needDraw = false
        }
      }
    })
  })
  return { cellSize, path }
}

// 计算 viewBox
const viewBox = computed(() => [
  -props.quietZone,
  -props.quietZone,
  props.size + props.quietZone * 2,
  props.size + props.quietZone * 2
].join(' '))

// 监听 props 变化
watchEffect(() => {
  try {
    const matrix = genMatrix(props.value, props.ecl)
    const result = transformMatrixIntoPath(matrix, props.size)
    path.value = result.path
    cellSize.value = result.cellSize
    error.value = null
  } catch (err) {
    error.value = err instanceof Error ? err : new Error('QR Code generation failed')
  }
})
</script>

<style scoped>
.error {
  color: red;
  border: 1px solid red;
  padding: 1rem;
}
</style>

step3: 调用二维码组件
C:\Users\wangrusheng\PycharmProjects\untitled3\src\views\ImgCode.vue

<template>
  <QrCode
    :value="qrCodeValue"
    :size="200"
    color="#333"
    logo="/logo.png"
    :logo-size="40"
    logo-background-color="white"
    :enable-linear-gradient="true"
  />
</template>

<script setup>
import QrCode from './QrCode.vue'
import { ref } from 'vue'
// 图片资源存放在 C:\Users\wangrusheng\PycharmProjects\untitled3\public\logo.png
// JSON.stringify() 是 JavaScript 中用于将对象或值转换为 JSON 格式字符串的核心方法,
//value="你们好,这里是二维码识别器,很高兴认识你们"
const qrCodeValue = ref(JSON.stringify({
  "data": [
    {
      "case_id": 3,
      "category_id": 4,
      "title": "as",
      "description": "ad",
      "price": 4500.0,
      "client_id": 5,
      "lawyer_id": 6,
      "status": "pending",
      "created_at": "2025-03-21T06:11:59",
      "updated_at": "2025-03-21T06:11:59",
      "category_name": "af"
    },
    {
      "case_id": 8,
      "category_id": 8,
      "title": "bs",
      "description": "bd",
      "price": 6000.0,
      "client_id": 5,
      "lawyer_id": 6,
      "status": "in_progress",
      "created_at": "2025-03-21T06:11:59",
      "updated_at": "2025-03-21T06:11:59",
      "category_name": "bf"
    }
  ]
}))
</script>

step4:路由

C:\Users\wangrusheng\PycharmProjects\untitled3\src\router\index.js
import ImgCode from '../views/ImgCode.vue'
{ path: '/imgcode', name: 'imgcode', component: ImgCode },

C:\Users\wangrusheng\PycharmProjects\untitled3\src\App.vue
<router-link to="/imgcode" active-class="active-link">二维码</router-link>

///我是分割线
解码部分
step101:安装依赖 pip install pyzbar Pillow,你去网站上,随便找个二维码生成器,然后将生成的二维码保存本地

step102:解析C:\Users\wangrusheng\PycharmProjects\FastAPIProject1\hello.py

from pyzbar.pyzbar import decode
from PIL import Image

# 二维码图片路径 C:\Users\wangrusheng\Downloads
old_file = r'C:\Users\wangrusheng\Downloads\logoz.png'

try:
    # 打开图片文件
    with Image.open(old_file) as img:
        # 解析二维码
        decoded_objects = decode(img)

        if not decoded_objects:
            print("未检测到二维码内容。")
        else:
            for obj in decoded_objects:
                # 解码数据(假设内容为UTF-8文本)
                data = obj.data.decode('utf-8')
                print("解析结果:", data)

except FileNotFoundError:
    print(f"错误:文件 '{old_file}' 不存在。")
except Exception as e:
    print(f"解析时发生错误: {str(e)}")

step103:运行

(.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1> python hello.py 
解析结果: 能不能点点赞  点点关注,我谢谢大家
(.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1> 

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2334980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c#和form实现WebSocket在线聊天室

c#和form实现WebSocket在线聊天室 功能点 后端程序 (Program.cs)​​1.WebSocket 聊天服务器核心功能​​a.管理客户端连接&#xff08;ConnectionManager 类&#xff09;b.支持公聊消息广播&#xff08;所有用户可见&#xff09;c.支持私聊消息&#xff08;通过 用户ID 格式指…

量子代理签名:量子时代的数字授权革命

1. 量子代理签名的定义与核心原理 量子代理签名&#xff08;Quantum Proxy Signature, QPS&#xff09;是经典代理签名在量子信息领域的延伸&#xff0c;允许原始签名者&#xff08;Original Signer&#xff09;授权给代理签名者&#xff08;Proxy Signer&#xff09;代为签署文…

「Unity3D」TextMeshPro中的TMP_InputField,用来实现输入框的几个小问题

第一&#xff0c;正确设置Scrollbar。 设置Scrollbar之后&#xff0c;不能设置Text Component的Font Size为Auto Size&#xff0c;否则Scrollbar无法正确计算显示。 那么&#xff0c;要想自动适配字体大小&#xff0c;可以让Placeholder中的Font Size设置为Auto&#xff0c;这…

Docker 介绍 · 安装详细教程

为什么选择 Docker&#xff1f; ✅ 环境一致性 – 告别“在我机器上能跑”的问题&#xff0c;确保开发、测试、生产环境一致。 ✅ 高效轻量 – 秒级启动&#xff0c;资源占用远低于传统虚拟机。 ✅ 跨平台支持 – 可在任何支持 Docker 的环境中运行&#xff0c;包括云服务器、…

vulnhub:sunset decoy

靶机下载地址https://www.vulnhub.com/entry/sunset-decoy,505/ 渗透过程 简单信息收集 nmap 192.168.56.0/24 -Pn # 确定靶机ip&#xff1a;192.168.56.121 nmap 192.168.56.121 -A -T4 # 得到开放端口22,80 在80端口得到save.zip&#xff0c;需要密码解压。 john破解压缩…

方案精读:71页制造企业一体化ERP系统项目实施方案【附全文阅读】

今天聊聊制造企业 ERP 系统项目实施方案。 某钾肥企业在发展中面临信息化难题,像物资编码不规范、业务手工化、财务业务脱节等 。为此,打造 “流程驱动,业务整合” 的一体化 ERP 管理平台很关键。它涵盖采购、销售、生产、运营流程,实现供应链、预算、资金、财务整…

MATLAB遇到内部问题,需要关闭,Crash Decoding : Disabled - No sandbox or build area path

1.故障界面 MATLAB运行时突然中断&#xff0c;停止运行。故障界面如图&#xff1a; MATLAB Log File: C:\Users\wei\AppData\Local\Temp\matlab_crash_dump.21720-1 ------------------------------------------------ MATLAB Log File -----------------------------------…

【Redis】Redis C++使用

一、Redis的自定义网络协议 1.1 为什么可以编写出一个自定义的Redis客户端 为什么我们可以编写出一个自定义的Redis客户端&#xff1f;因为Redis公开了自己的自定义协议。而对于一些其他软件的客户端&#xff0c;我们无法编写出一个自定义的Redis客户端&#xff0c;因为他们没…

每日一题(小白)暴力娱乐篇19

样例&#xff1a; 6 1 1 4 5 1 4 输出&#xff1a; 56 66 52 44 54 64 分析题意可以得知&#xff0c;就是接收一串数字&#xff0c;将数字按照下标每次向右移动一位&#xff08;末尾循环到第一位&#xff09;&#xff0c;每次移动玩计算一下下标和数字的乘积且累加。 ①接收…

25级总分413数学一142专业124东南大学820考研经验电子信息通信工程,真题,大纲,参考书。

我是南京理工大学的本科生&#xff0c;25 考研一战东大&#xff0c;政治 69&#xff0c;英一 78&#xff0c;数一 142&#xff0c;专业课&#xff08;820&#xff09;124&#xff0c;总分 413。我从 3 月正式开始备考&#xff0c;专业课跟着无线电论坛jenny 老师进行学习&#…

【数据结构_6上篇】有关链表的oj题

import java.util.*;/* public class ListNode {int val;ListNode next null;ListNode(int val) {this.val val;} }*/ public class Partition {public ListNode partition(ListNode pHead, int x) {// write code here//1.首先要判断链表是否为空的情况if(pHead null){retu…

【QT】QWidget 概述与核心属性(API)

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Qt 目录 一&#xff1a;&#x1f525; 控件概述 &#x1f98b; 控件体系的发展阶段 二&#xff1a;&#x1f525; QWidget 核心属性 &#x1f98b; 核心属性概览&#x1f98b; 用件可用&#xff08…

微服务篇——SpringCloud

服务注册 Spring Cloud5大组件有哪些&#xff1f; 服务注册和发现是什么意思&#xff1f;Spring Cloud如何实现服务注册发现&#xff1f; nacos与eureka的区别 负载均衡 如何实现负载均衡&#xff1f; Ribbon负载均衡的策略有哪些&#xff1f; 如何自定义负载均衡的策略&…

如何使用PyCharm自动化测试

如何使用PyCharm自动化测试 1.打开PyCharm右击文件&#xff0c;点击新建项目 按照如图配置&#xff0c;然后点击创建 2.创建好后&#xff0c;点击文件&#xff0c;然后点击设置 按照如图步骤&#xff0c;查看selenium和webdriver-manager是否存在 3.以上都完成后按照如图创…

记一次某网络安全比赛三阶段webserver应急响应解题过程

0X01 任务说明 0X02 靶机介绍 Webserver&#xff08;Web服务器&#xff09;是一种软件或硬件设备&#xff0c;用于接收、处理并响应来自客户端&#xff08;如浏览器&#xff09;的HTTP请求&#xff0c;提供网页、图片、视频等静态或动态内容&#xff0c;是互联网基础设施的核心…

复现QGIS-MCP教程

由于Claude国内下载不了尝试使用Cursor 下载安装Cursor Cursor - The AI Code Editor 本示例安装的是0.46版本 UV安装 简介 安装 安装成功 配置环境变量 验证 下载代码 git clone gitgithub.com:jjsantos01/qgis_mcp.git QGIS插件安装 文件拷贝 您需要将 qgis_mcp_plu…

docker部署certimateSSL证书管理自动续签

开源certimate项目地址&#xff1a;https://github.com/usual2970/certimate 官方文档地址&#xff1a;https://docs.certimate.me/docs/introduction 与certbot对比 维度CertbotCertimate安装方式通过包管理器&#xff08;如apt/yum&#xff09;安装支持二进制文件、Docker…

R语言——直方图

参考资料&#xff1a;学习R 如果我们要研究一个连续变量的分布&#xff0c;直方图是最佳的选择。 1、base绘图 在base中可以使用hist函数绘制直方图&#xff0c;与plot函数一样&#xff0c;它没有data参数&#xff0c;须把数据框置于with中。 data(obama_vs_mccain,package&q…

第4节:Python编程基础 - Python语法快速回顾

1. Python简介与环境配置 Python是一种高级、解释型、通用的编程语言&#xff0c;由Guido van Rossum于1991年首次发布。 它以简洁明了的语法和强大的功能而闻名&#xff0c;广泛应用于Web开发、数据分析、人工智能、科学计算等领域。 1.1 Python的特点 简单易学&#xff1a;…

十四、C++速通秘籍—函数式编程

目录 上一章节&#xff1a; 一、引言 一、函数式编程基础 三、Lambda 表达式 作用&#xff1a; Lambda 表达式捕获值的方式&#xff1a; 注意&#xff1a; 四、函数对象 函数对象与普通函数对比&#xff1a; 五、函数适配器 1、适配普通函数 2、适配 Lambda 表达式 …