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

二维码生成工具使用@uqrcode/js,版本4.0.7

官网地址:uQRCode 中文文档(不建议看可能会被误导)

本项目采用了npm引入方式,也可通过插件市场引入,使用上会略有不同


准备工作:

安装:pnpm add @uqrcode/js

引入:import UQRCode from '@uqrcode/js/uqrcode'


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

javascript 复制代码
<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并转为在线url
        const fileRes: any = await base64ToTempFile({ image: canvas.toDataURL() })
        // 转为临时url
        uni.downloadFile({
          url: fileRes.data.fileUrl,
          success: (res) => {
            pageData.qrCodePath = res.tempFilePath
          }
        });

      });
};

页面绘制:

javascript 复制代码
 <!-- 隐藏的 Canvas(用于绘制截图) -->
 <canvas
   canvas-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.screenWidth
    screenHeight.value = systemInfo.screenHeight

    // 2. 设置canvas尺寸(考虑设备像素比)
    const dpr = systemInfo.pixelRatio || 1
    const 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 * rpxToPx
    const fontSizeDesc = 32 * rpxToPx
    const centerX = canvasWidth / 2

    // 标题
    canvasContext.setFontSize(fontSizeTitle)
    canvasContext.setFillStyle('#000000') // 改为黑色确保可见
    canvasContext.setTextAlign('center')
    const displayText = pageData.name?.length > 7
        ? pageData.name.substring(0, 6) + '...'
        : pageData.name
    canvasContext.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, // 考虑DPI
      height: 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
    })
  }
}
相关推荐
蓉妹妹5 小时前
React+Taro 微信小程序做一个页面,背景图需贴手机屏幕最上边覆盖展示
react.js·微信小程序·taro
java1234_小锋8 小时前
[免费]微信小程序宠物医院管理系统(uni-app+SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
spring boot·微信小程序·宠物医院·小程序宠物医院·springboot宠物医院
ljbaofu_CSDN8 小时前
微信小程序开发中,请求数据列表,第一次请求10条,滑动到最低自动再请求10条,后面请求的10条怎么加到第一次请求的10条后面?
微信小程序·小程序
时间识人8 小时前
【无标题】
vue.js·微信小程序·taro
百锦再8 小时前
微信小程序学习基础:从入门到精通
前端·vue.js·python·学习·微信小程序·小程序·pdf
Bald Baby9 小时前
uniapp实现H5、APP、微信小程序播放.m3u8监控视频
微信小程序·小程序·uni-app·音视频·视频
stpzhf9 小时前
uni-app 排坑
uni-app
资深前端之路9 小时前
uniapp vue 开发微信小程序 分包梳理经验总结
uni-app
-25℃9 小时前
记一次奇葩的错误,uniapp @tap点击失效
微信小程序·uni-app