Taro之玩转QRCode的生成、保存、分享

1,289 阅读3分钟

介绍

基于Taro,最近写了一个小程序,其中有个小功能是根据后端提供的一个Url,生成一个二维码图片。后这个图片长按,弹出按钮列表,点击【保存到本地】,则能够保存二维码图片到本地相册。

问题抛出

测试反馈,点击【保存到本地】后,提示保存成功,实际手机相册中图片不存在。

问题初步分析

涉及图片保存的地方有多处,有些地方成功,有些地方不成功。带着疑惑分析问题发现:

成功的地方,img 绑定的src 指向的内容,都是图片格式的Url。

而失败的地方,指向的是一个base64格式的字符串,且格式为:data:image/svg+xml;base64

问题判定:微信小程序,应该无法识别该格式内容。

解决问题

  1. 处理依据

    基于目前该功能只在微信小程序中使用,所以查询【weapp-qrcode】相关的npm库。找了一个最近上架的工具:weapp-qrcode-canvas-2d(其他的都太老了)

  2. 初始代码

根据readme,编写代码如下:

<script setup lang="ts">
import { reactive, onMounted } from 'vue';
import Taro from '@tarojs/taro';
import drawQrcode from 'weapp-qrcode-canvas-2d';

const props = defineProps<Props>();

type Props = {
  url: string;
  width: number;
  height: number;
};

const refData = reactive({
  qrCodeURL: ''
});

onMounted(() => {
  const query = Taro.createSelectorQuery();

  query
    .select('#myQrcode')
    .fields({
      node: true,
      size: true
    })
    .exec(res => {
      const canvas = res[0].node;

      // 调用方法drawQrcode生成二维码
      drawQrcode({
        canvas,
        canvasId: 'myQrcode',
        width: props.width,
        height: props.height,
        background: '#ffffff',
        foreground: '#000000',
        text: props.url
      });

      // 获取临时路径(得到之后,想干嘛就干嘛了)
      Taro.canvasToTempFilePath({
        canvasId: 'myQrcode',
        canvas,
        x: 0,
        y: 0,
        width: props.width,
        height: props.height,
        destWidth: 600,
        destHeight: 600,
        success(res) {
          refData.qrCodeURL = res.tempFilePath;
          console.log('二维码临时路径:', res.tempFilePath);
        },
        fail(res) {
          console.error(res);
        }
      });
    });
});
</script>

<template>
  <div>
    <canvas
      id="myQrcode"
      type="2d"
      v-show="false"
      :style="{ width: `${props.width}px`, height: `${props.height}px` }"
    ></canvas>
    <img
      v-if="refData.qrCodeURL"
      :src="refData.qrCodeURL"
      :style="{ width: `${props.width}px`, height: `${props.height}px` }"
      alt="QR Code"
      :show-menu-by-longpress="true"
    />
    <view class="h-[35px]"></view>
  </div>
</template>

<style></style>

上述代码,在微信开发工具中和Android手机上都是能够正常运行的。但是在IOS手机上,二维码是看不见的。

难受了,这是为啥?

  1. 问题分享并百度

    说是v-show=false这个导致,在IOS上拿不到画布对象了。所以就变向救国了,修改代码如下:

<canvas id="myQrcode" type="2d" 
:style="{ width: `${props.width}px`, height: `${props.height}px`, left: '9000px', position: 'fixed' }">
</canvas>

在百度的过程中,说微信小程序不支持啥2d格式的canvas等问题,存在误导。只要把canvas移出屏幕可视范围就可以了。

过程总结

业务:先从后端获取一个Url,然后把这个Url显示成二维码图片,然后点击图片能够存储本地相册。

技术:使用weapp-qrcode-canvas-2d完成Url显示成二维码图片;image添加show-menu-by-longpress属性,完成长按保存本地。

问题处理:通过分析和百度,找到使用过程中的问题。

为啥题目是保存、分享等功能呢?因为只要能保存了,那么就能够分享,因为调用的是show-menu-by-longpress属性自带的功能。