首頁  >  文章  >  web前端  >  聊聊Vue3+qrcodejs如何產生二維碼並加入文字描述

聊聊Vue3+qrcodejs如何產生二維碼並加入文字描述

青灯夜游
青灯夜游轉載
2022-08-02 21:19:245197瀏覽

Vue3如何更好地使用qrcodejs產生二維碼並添加文字描述?以下這篇文章跟大家介紹Vue3 qrcodejs產生二維碼並加入文字描述,希望對大家有幫助。

聊聊Vue3+qrcodejs如何產生二維碼並加入文字描述

最近專案中有產生二維碼功能的需求,還需要在二維碼底部加入文字描述,並把二維碼和文字合併成一張圖下載的要求。

之前的項目有用到vue-qr,確實非常好用,但是考慮到添加文字描述,後面就選擇了qrcodejs#。 (學習影片分享:vue影片教學

文章專案基於《使用Vite建立Vue3專案實作記錄 》

https://juejin.cn/ post/7082307153192550430

#產生二維碼

##安裝

qrcodejs,並安裝其類型定義模組

npm i qrcode -S
npm install --save @types/qrcode
新全域二維碼元件

QRcode.vue,二維碼資訊及文字描述都由外部傳入

基本操作就是先呼叫

qrcode toDataURL方法,取得到二維碼的Base64圖片訊息,接著新建Image,再把圖片畫到Canvas

#最後加上自訂文字即可

要注意的是文字的位置是在圖片底部居中

qrCodeOptionqrcode相關配置,詳情qrcode - npm (npmjs.com)

<template>
  <canvas></canvas>
</template>

<script>
import QRCode from "qrcode";
import { onMounted, ref } from "vue";

const props = defineProps({
  //二维码存储内容
  qrUrl: {
    type: String,
    default: "Hello World"
  },
  // canvas width
  width: {
    type: Number,
    default: 400
  },
  // canvas height
  height: {
    type: Number,
    default: 400
  },
  // 二维码尺寸(正方形 长宽相同)
  qrSize: {
    type: Number,
    default: 360
  },
  // 二维码底部文字
  qrText: {
    type: String,
    default: "Hello World"
  },
  //底部说明文字字号
  qrTextSize: {
    type: Number,
    default: 24
  }
});

const qrCodeOption = {
  errorCorrectionLevel: "H",
  width: props.qrSize,
  version: 7
};

const canvas = ref<HTMLCanvasElement>();
/**
 * @argument qrUrl        二维码内容
 * @argument qrSize       二维码大小
 * @argument qrText       二维码中间显示文字
 * @argument qrTextSize   二维码中间显示文字大小(默认16px)
 */
const handleQrcode = () => {
  let dom = canvas.value as HTMLCanvasElement;
  QRCode.toDataURL(props.qrUrl, qrCodeOption)
    .then((url: string) => {
      // 画二维码里的logo// 在canvas里进行拼接
      const ctx = dom.getContext("2d") as CanvasRenderingContext2D;
      const image = new Image();
      image.src = url;
      setTimeout(() => {
        ctx.drawImage(image, (props.width - props.qrSize) / 2, 0, props.qrSize, props.qrSize);
        if (props.qrText) {
          //设置字体
          ctx.font = "bold " + props.qrTextSize + "px Arial";
          let tw = ctx.measureText(props.qrText).width; // 文字真实宽度
          let ftop = props.qrSize - props.qrTextSize; // 根据字体大小计算文字top
          let fleft = (props.width - tw) / 2; // 根据字体大小计算文字left
          ctx.fillStyle = "#fff";
          ctx.textBaseline = "top"; //设置绘制文本时的文本基线。
          ctx.fillStyle = "#333";
          ctx.fillText(props.qrText, fleft, ftop);
        }
      }, 0);
    })
    .catch((err: Error) => {
      console.error(err);
    });
};

onMounted(() => {
  handleQrcode();
});
</script>

<style></style>

思考與最佳化setTimeout改為Promise

到這裡二維碼的功能基本上可以使用了,但是我在想為什麼這裡需要使用到

setTimeout呢?

如果是

nextTick行不行?答案是不行的,原因是nextTick是微任務,實在DOM刷新之前就執行了,而setTimeout在之後執行。

可以注意到程式碼中有新建

Image方法,圖片載入是異步的,所以有更好的處理方法嗎?

可以改用

Promise,在圖片的onload方法中回傳圖片就可以了,所以改為寫下handleQrcode

const handleQrcode = () => {
  let dom = canvas.value as HTMLCanvasElement;
  QRCode.toDataURL(props.qrUrl, qrCodeOption)
    .then((url: string) => {
      // 画二维码里的logo// 在canvas里进行拼接
      const ctx = dom.getContext("2d") as CanvasRenderingContext2D;
      const image = new Image();
      image.src = url;
      new Promise<htmlimageelement>((resolve) => {
        image.onload = () => {
          resolve(image);
        };
      }).then((img: HTMLImageElement) => {
        // console.log(img, ctx)
        ctx.drawImage(img, (props.width - props.qrSize) / 2, 0, props.qrSize, props.qrSize);
        if (props.qrText) {
          //设置字体
          ctx.font = "bold " + props.qrTextSize + "px Arial";
          let tw = ctx.measureText(props.qrText).width; // 文字真实宽度
          let ftop = props.qrSize - props.qrTextSize; // 根据字体大小计算文字top
          let fleft = (props.width - tw) / 2; // 根据字体大小计算文字left
          ctx.fillStyle = "#fff";
          ctx.textBaseline = "top"; //设置绘制文本时的文本基线。
          ctx.fillStyle = "#333";
          ctx.fillText(props.qrText, fleft, ftop);
        }
      });
    })
    .catch((err: Error) => {
      console.error(err);
    });
};</htmlimageelement>

二維碼下載

有了二維碼就需要下載,補充下載方法,在元件內部加上

#直接使用

canvas toDataURL方法轉成Base64

//保存图片
const savePic = () => {
  let dom = canvas.value as HTMLCanvasElement;
  let a = document.createElement("a");
  //将二维码面板处理为图片
  a.href = dom.toDataURL("image/png", 0.5);
  a.download = props.qrUrl + ".png";
  a.click();
};

defineExpose({ savePic });

父元件呼叫

#全域註冊

可以把元件註冊為全域元件,可以參考文章

Vue專案中的實用技巧記錄

其中包含

webpackvite 遍歷vue檔案註冊全域元件

呼叫元件
<template>
  <div>
    <qrcode></qrcode>
  </div>
</template>

效果如圖

聊聊Vue3+qrcodejs如何產生二維碼並加入文字描述

多二維碼遍歷下載

上面補充的下載方法中,需要使用

defineExpose,不然會呼叫不到子元件方法

<template>
  <div>
    <qrcode></qrcode>
    <el-button>downlaod</el-button>
  </div>
</template>

<script>
import { reactive, ref } from "vue";
const qrcode = ref();
const qrcodeList = reactive([
  { id: 1, label: "山卡拉OK" },
  { id: 2, label: "伍六七" },
  { id: 3, label: "梅小姐" },
  { id: 4, label: "鸡大保" },
  { id: 5, label: "小飞鸡" }
]);

const downloadAll = () => {
  qrcode.value.map((item: any) => {
    item.savePic();
  });
};
</script>
Option Api案例

Option Api的案例如下

src/components/QRcodeOption.vue · LWH/vite-vue3-project - 碼雲- 開源中國(gitee.com)

src/views/qrcode/qrcode2.vue · LWH/vite-vue3-project - 碼雲- 開源中國(gitee.com)

(學習影片分享:

web前端開發程式設計基礎影片

以上是聊聊Vue3+qrcodejs如何產生二維碼並加入文字描述的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除