微信小程序-二维码绘制

news/2025/2/24 16:33:54

wxml

<view bindlongtap="saveQrcode">
  <!-- 二维码 -->
  <view style="position: absolute;background-color: #FFFAEC;width: 100%;height: 100vh;">
    <canvas canvas-id="myQrcode" style="width: 200px; height: 200px;background-color: azure;position: fixed;top: 999px;" ></canvas>
  </view>
  <!-- 绘制的背景图 -->
  <canvas type="2d" id="newQrcode" style="width: 100%;height: 700px;z-index: 99;"></canvas>
</view>

wxss

/* pages/QRcode/QRcode.wxss */
.canvas {
    width: 100%;
    height: -webkit-calc(100% - 44px);
    height: -moz-calc(100% - 44px);
    height: calc(100% - 44px);
    background: #fff;
  }

js

// pages/index/index.js
import QRCode from './weapp.qrcode.esm';

let textCanvas;

Page({
  data: {
    qrcodeVisible: true // 控制二维码是否显示
  },

  onReady() {
    // 等待二维码绘制完成后再获取临时文件路径
    this.generateQRCode().then((tempQrcodePath) => {
      this.drawCompositeImage(tempQrcodePath);
    }).catch((err) => {
      console.error('生成二维码临时文件失败:', err);
      wx.showToast({
        title: '生成二维码临时文件失败',
        icon: 'none'
      });
    });
  },

  // 生成二维码并获取临时文件路径
  generateQRCode() {
    return new Promise((resolve, reject) => {
      // 初始化二维码
      QRCode({
        width: 200,
        height: 200,
        canvasId: 'myQrcode',
        colorDark: '#000000',
        colorLight: '#ffffff',
        text: 'http://lxj.yzwdblzs.xyz/',
      });

      // 延迟一段时间确保二维码绘制完成,可根据实际情况调整延迟时间
      setTimeout(() => {
        wx.canvasToTempFilePath({
          canvasId: 'myQrcode',
          success: (res) => {
            console.log('二维码路径:', res);
            const tempQrcodePath = res.tempFilePath;
            resolve(tempQrcodePath);
          },
          fail: (err) => {
            console.error('获取临时文件失败', err);
            reject(err);
          }
        });
      }, 500);
    });
  },

  drawCompositeImage(tempQrcodePath) {
    return new Promise((resolve, reject) => {
      wx.createSelectorQuery().select('#newQrcode')
       .fields({
          node: true,
          size: true
        })
       .exec((res) => {
          textCanvas = res[0].node; // 获取 canvas 节点
          const textCtx = textCanvas.getContext('2d');

          const dpr = wx.getSystemInfoSync().pixelRatio; // 获取设备像素比
          textCanvas.width = res[0].width * dpr;
          textCanvas.height = res[0].height * dpr;
          textCtx.scale(1, 1);
          textCtx.fillRect(0, 0, 200, 200);
          textCtx.clearRect(0, 0, textCanvas.width, textCanvas.height);
          textCtx.beginPath();

          const bg = textCanvas.createImage();
          bg.src = 'http://lxj.yzwdblzs.xyz/img/noName.png';
          bg.onload = () => {
            console.log('背景图加载成功');
            const qrImage = textCanvas.createImage();
            qrImage.src = tempQrcodePath;
            qrImage.onload = () => {
              console.log('二维码加载成功');
              // 绘制背景图
              this.drawBackground(textCtx, bg);
              // 绘制二维码
              this.drawQRCode(textCtx, tempQrcodePath);
              resolve();
            };
            qrImage.onerror = () => {
              console.error('二维码加载失败');
              reject(new Error('二维码加载失败'));
            };
          };
          bg.onerror = () => {
            console.error('背景图加载失败');
            reject(new Error('背景图加载失败'));
          };
        });
    });
  },

  drawBackground(textCtx, bg) {
    const bgWidth = bg.width;
    const bgHeight = bg.height;
    // 计算缩放比例
    const scaleX = textCanvas.width / bgWidth;
    const scaleY = textCanvas.height / bgHeight;
    const scale = Math.max(scaleX, scaleY); // 选择最大的比例以适应 canvas
    // 计算背景图绘制的尺寸
    const drawWidth = bgWidth * scale;
    const drawHeight = bgHeight * scale;
    // 绘制背景图
    textCtx.drawImage(bg, 0, 0, drawWidth, drawHeight);
  },

  drawQRCode(textCtx, tempQrcodePath) {
    const qrWidth = 550; // 二维码宽度
    const qrHeight = 550; // 二维码高度
    const qrX = (textCanvas.width - qrWidth + 40) / 2; // 水平居中
    const qrY = (textCanvas.height - qrHeight + 940) / 2; // 垂直居中
    // 绘制二维码到背景图上
    const qrImage = textCanvas.createImage();
    qrImage.src = tempQrcodePath;
    qrImage.onload = () => {
      textCtx.drawImage(qrImage, qrX, qrY, qrWidth, qrHeight);
      // 合成图像成功后隐藏二维码
      this.setData({
        qrcodeVisible: false
      });
    };
    qrImage.onerror = () => {
      console.error('二维码绘制失败');
    };
  },

  // 长按保存
  // 最终合成图像保存到临时路径
  saveQrcode() {
    wx.getSetting({
      success: (res) => {
        if (!res.authSetting['scope.writePhotosAlbum']) {
          wx.authorize({
            scope: 'scope.writePhotosAlbum',
            success: () => {
              this.saveCanvasToAlbum();
            },
            fail: (err) => {
              console.error('用户拒绝授权保存相册', err);
              wx.showToast({
                title: '未授权保存相册',
                icon: 'none'
              });
            }
          });
        } else {
          this.saveCanvasToAlbum();
        }
      }
    });
  },

  saveCanvasToAlbum() {
    wx.showLoading({
      title: '正在保存图片...',
    });
    wx.canvasToTempFilePath({
      canvas: textCanvas,
      success: (finalRes) => {
        wx.saveImageToPhotosAlbum({
          filePath: finalRes.tempFilePath,
          success: () => {
            wx.hideLoading();
            wx.showToast({
              title: '保存成功',
            });
          },
          fail: (err) => {
            wx.hideLoading();
            console.error('保存失败', err);
            wx.showToast({
              title: '保存失败',
              icon: 'none'
            });
          },
        });
      },
      fail: (err) => {
        wx.hideLoading();
        console.error('合成图像失败', err);
        wx.showToast({
          title: '合成图像失败',
          icon: 'none'
        });
      },
    });
  }
});

引入文件


http://www.niftyadmin.cn/n/5864576.html

相关文章

CentOS 7.9 解决 python3 报错 ModuleNotFoundError: No module named ‘_ssl‘ 的问题

方法&#xff1a;直接将系统的 openssl 升级到高版本 OpenSSL 1.1.1 具体步骤&#xff1a; 1. 手动编译 OpenSSL 1.1.1 bash # 安装编译依赖 sudo yum install -y perl-core zlib-static# 下载并编译 OpenSSL wget https://www.openssl.org/source/openssl-1.1.1w.tar.gz tar…

【网络安全】常见的web攻击

1、SQL注入攻击 定义&#xff1a; 攻击者在HTTP请求中注入恶意的SQL代码&#xff0c;当服务器利用参数构建SQL语句的时候&#xff0c;恶意的SQL代码被一起构建,并在数据库中执行。 示例&#xff1a; 用户登录&#xff1a; 输入用户名xx&#xff0c; 密码 or 1 …

C#: 日志函数

背景&#xff1a; 1.常见的官方日志模块项目过于复杂&#xff0c;且配置过于繁琐&#xff0c;针对这种现象&#xff0c;实现在大型项目中快速定位错误问题&#xff1b; 实现思路&#xff1a; 1.设置当前日志文件路径&#xff08;获取到当前文件应用程序路径 \ErrorLog) 2.判…

五、Three.js顶点UV坐标、纹理贴图

一部分来自1. 创建纹理贴图 | Three.js中文网 &#xff0c;一部分是自己的总结。 一、创建纹理贴图 注意&#xff1a;把一张图片贴在模型上就是纹理贴图 1、纹理加载器TextureLoader 注意&#xff1a;将图片加载到加载器中 通过纹理贴图加载器TextureLoader的load()方法加…

Qt 中的线程池QRunnable和QThreadPool

Qt 中的线程池QRunnable和QThreadPool 一、QThreadPool类介绍 QThreadPool 是 Qt 框架中用于管理线程池的类&#xff0c;它提供了一种高效的方式来管理和复用线程&#xff0c;避免频繁创建和销毁线程带来的开销。 1. 基本概念 QThreadPool 是一个全局的线程池&#xff0c;它…

猿大师播放器:智慧安防网页播放RTSP H.265实时监控革命,无需转码终极解决方案

一、智慧安防的致命瓶颈&#xff1a;当传统技术拖累生命安全 在智慧城市、工业安全、应急指挥等场景中&#xff0c;实时视频监控是守护生命与财产的核心防线。然而&#xff0c;传统RTSP播放方案在延迟、成本、稳定性上的缺陷&#xff0c;正在成为安防系统的“阿喀琉斯之踵”。…

解锁Redis的深层能力:事务与消息队列的最佳实践

在当今数据驱动的世界里&#xff0c;高效的数据管理和处理成为了每一个成功应用的核心。Redis&#xff0c;作为一款高性能的内存数据库&#xff0c;不仅以其快速读写能力著称&#xff0c;还提供了诸如事务、持久化、以及灵活的消息队列实现等高级功能&#xff0c;使得开发者能够…

【Python爬虫(55)】Scrapy进阶:深入剖析下载器与下载中间件

【Python爬虫】专栏简介&#xff1a;本专栏是 Python 爬虫领域的集大成之作&#xff0c;共 100 章节。从 Python 基础语法、爬虫入门知识讲起&#xff0c;深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑&#xff0c;覆盖网页、图片、音频等各类数据爬取&#xff…