当前位置: 首页 > article >正文

UniApp+Vue3微信小程序二维码生成、转图片、截图保存整页

二维码生成工具使用@uqrcode/js,版本4.0.7
官网地址:uQRCode 中文文档(不建议看可能会被误导)
本项目采用了npm引入方式,也可通过插件市场引入,使用上会略有不同


准备工作:
安装:pnpm add @uqrcode/js
引入:import UQRCode from '@uqrcode/js/uqrcode'


二维码生成及转图片逻辑:


<view class="qrcode-icon"><!-- 设置 canvas 的固定尺寸 --><canvas type="2d" id="qrcodeCanvas" canvas-id="qrcodeCanvas" style="width: 360rpx; height: 360rpx;"></canvas>
</view>// 生成二维码
const generateWXQRCode = async () => {const query = uni.createSelectorQuery();query.select('#qrcodeCanvas').fields({ node: true, size: true }, () => {}).exec(async (res) => {if (!res[0]?.node) {console.error('未找到二维码Canvas节点');return;}const canvas = res[0].node;const ctx = canvas.getContext('2d');const { width, height } = res[0];// 设置 canvas 的绘制尺寸(避免模糊)canvas.width = width;canvas.height = height;// 创建二维码实例const qrcode = new UQRCode({data: `111111`,size: Math.min(width, height),canvasContext: ctx});// 绘制二维码await qrcode.make();await qrcode.draw();// 获取base64并转为在线urlconst fileRes: any = await base64ToTempFile({ image: canvas.toDataURL() })// 转为临时urluni.downloadFile({url: fileRes.data.fileUrl,success: (res) => {pageData.qrCodePath = res.tempFilePath}});});
};

页面绘制:
 

 <!-- 隐藏的 Canvas(用于绘制截图) --><canvascanvas-id="screenshotCanvas":style="{width: `${screenWidth}px`,height: `${screenHeight}px`,position: 'fixed',left: '-9999px'}">
</canvas>const screenWidth = ref(300)
const screenHeight = ref(400)
// 保存当前页面为图片
const takeScreenshot = async () => {try {// 1. 获取系统信息const systemInfo = await uni.getSystemInfo()screenWidth.value = systemInfo.screenWidthscreenHeight.value = systemInfo.screenHeight// 2. 设置canvas尺寸(考虑设备像素比)const dpr = systemInfo.pixelRatio || 1const canvasWidth = Math.min(screenWidth.value, 750)const canvasHeight = Math.min(screenHeight.value, 1334)const rpxToPx = screenWidth.value / 750// 3. 获取canvas上下文const canvasContext = uni.createCanvasContext('screenshotCanvas')// 4. 绘制白色背景(确保有内容)canvasContext.setFillStyle('#FFFFFF')canvasContext.fillRect(0, 0, canvasWidth, canvasHeight)// 5. 绘制背景图(使用绝对路径)const bgPath = '/subPages/static/qrcode-bg.png' // 确保图片存在于此路径try {canvasContext.drawImage(bgPath, 0, 0, canvasWidth, canvasHeight)} catch (err) {console.error('背景图加载失败:', err)// 使用备用颜色canvasContext.setFillStyle('#F0F0F0')canvasContext.fillRect(0, 0, canvasWidth, canvasHeight)}// 6. 绘制文本内容const fontSizeTitle = 72 * rpxToPxconst fontSizeDesc = 32 * rpxToPxconst centerX = canvasWidth / 2// 标题canvasContext.setFontSize(fontSizeTitle)canvasContext.setFillStyle('#000000') // 改为黑色确保可见canvasContext.setTextAlign('center')const displayText = pageData.name?.length > 7? pageData.name.substring(0, 6) + '...': pageData.namecanvasContext.fillText(displayText, centerX, 260 * rpxToPx)// 副标题canvasContext.setFontSize(fontSizeDesc)canvasContext.fillText('邀请您加入车队', centerX, 320 * rpxToPx)// 绘制二维码const qrSize = 200;const qrX = (canvasWidth - qrSize) / 2;const qrY = 480 * rpxToPx;canvasContext.drawImage(pageData.qrCodePath, qrX, qrY, qrSize, qrSize);// 失效时间canvasContext.setFillStyle('#000000')canvasContext.fillText(`${pageData.selectedTime} 23:59:59后失效`,centerX,920 * rpxToPx)// 7. 执行绘制(关键修改)await new Promise<void>((resolve, reject) => {canvasContext.draw(true, () => {setTimeout(() => {// 检查Canvas内容console.log('Canvas绘制完成')resolve()}, 500) // 增加延迟确保渲染完成})})// 8. 生成临时文件const { tempFilePath } = await uni.canvasToTempFilePath({canvasId: 'screenshotCanvas',quality: 1, // 最高质量width: canvasWidth * dpr, // 考虑DPIheight: canvasHeight * dpr})// 9. 保存到相册await uni.saveImageToPhotosAlbum({filePath: tempFilePath})uni.showToast({title: '保存成功',icon: 'success'})} catch (err) {console.error('截图失败:', err)uni.showToast({title: '保存失败: ' + (err.errMsg || '未知错误'),icon: 'none',duration: 3000})}
}

http://www.lryc.cn/news/2386624.html

相关文章:

  • 8.2 线性变换的矩阵
  • 【2025】嵌入式软考中级部分试题
  • Antd中Upload组件封装及使用:
  • Linux环境基础开发工具->vim
  • 跳板问题(贪心算法+细节思考)
  • RuoYi前后端分离框架集成UEditorPlus富文本编辑器
  • IPD流程落地:项目任务书Charter开发
  • Vue 2 混入 (Mixins) 的详细使用指南
  • day020-sed和find
  • OpenGL Chan视频学习-4 Vertex Buffers and Drawing a Triangle in OpenGL
  • 数据库事务的四大特性(ACID)
  • 网络安全全知识图谱:威胁、防护、管理与发展趋势详解
  • FreeRTOS 在物联网传感器节点的应用:低功耗实时数据采集与传输方案
  • 解决 iTerm2 中 nvm 不生效的问题(Mac 环境)
  • Linux环境下基于Docker安装 PostgreSQL数据库并配置 pgvector
  • (9)-java+ selenium->元素定位之By name
  • 深浅拷贝?
  • Beckhoff PLC 功能块 FB_CTRL_ACTUAL_VALUE_FILTER (模拟量滤波)
  • Mysql在SQL层面的优化
  • JVM规范之栈帧
  • 【C++指南】string(四):编码
  • 深度学习之序列建模的核心技术:LSTM架构深度解析与优化策略
  • AI量化交易是什么?它是如何重塑金融世界的?
  • 分布式事务处理方案
  • CVE-2024-36467 Zabbix权限提升
  • Dify中的自定义模型插件开发例子:以xinference为例
  • crud方法命名示例
  • 尚硅谷redis7 33-36 redis持久化之RDB优缺点及数据丢失案例
  • No such file or directory: ‘ffprobe‘
  • 计算机网络-WebSocket/DNS/Cookie/Session/Token/Jwt/Nginx