Vue で QR コードを表示する(TypeScript 対応)

qrcode パッケージを使用して Vue で QR コード生成する TypeScript での 実装例です。Vue に依存しない qrcode パッケージを使用するので、Vue 以外でも使用できます。

やりたいこと

qrcode というパッケージを使用して Vue で QR コード生成を実装したいと思います。

Vue に特化した QR コード生成パッケージ vue-qrcode もあるのですが、Vue と密結合していると、Vue 自体のバージョンアップが発生した際に、そのバージョンアップの対応がなされるまで使用できないといったリスクがあります。また Vue を React や Svelte に変更しても同じパッケージを使用できるのもメリットです。

ちなみに vue-qrcode も内部的には qrcode を使ってます。

環境

TypeScript
5.0.2
Vite
4.4.5
Vue
3.3.4
QRCode
1.5.3

準備

qrcode パッケージのインストール

npm install --save qrcode

TypeScript の場合は @types/qrcode も追加します。

npm install --save-dev @types/qrcode

実装例

QRCode をインポートし、QRCode.toDataURL() に QR コード化したい文字列を渡すことで データ URL 化された QR コードの画像 (デフォルトは PNG 形式) を得ることができます。

QRCode.toDataURL() の仕様は以下の通りです。

toDataURL(text, [options], [cb(error, url)])
toDataURL(canvasElement, text, [options], [cb(error, url)])

Returns a Data URI containing a representation of the QR Code image. If provided, canvasElement will be used as canvas to generate the data URI. - qrcode - npm

img 要素に描画

QRCode.toDataURL() はデータ URL を返すので、以下の実装例のように img 要素の src 属性に直接渡すことで QR コード画像を表示することができます。

<script setup lang="ts">
import { ref } from "vue";
import QRCode from "qrcode";

const text = ref<string>("");
const src = ref<string>("");

const handlerTextChange = async (e: Event) => {
  const target = e.target as HTMLInputElement;
  text.value = target.value;
  src.value = await QRCode.toDataURL(target.value);
}
</script>

<template>
  <div class="container">
    <input type="text" :value="text" @change="handlerTextChange"/>
    <img :src="src" />
    <a v-if="src" :href="src" download="qr.png">Download</a>
  </div>
</template>

<style scoped>
.container {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  width: 375px;
  margin: 0 auto;
  padding: 24px;
  text-align: center;
}

img {
  display: block;
  width: 150px;
  margin: 0 auto;
}
</style>

こんな感じになります。

img 要素に描画

canvas 要素に描画

QRCode.toDataURL()canvas 要素を渡すことで、その canvas 要素に直接 QR コードを描画することもできます。 以下はその実装例です。

<script setup lang="ts">
import { ref } from "vue";
import QRCode from "qrcode";

const text = ref<string>("");
const canvas = ref<HTMLCanvasElement>();
const dataUrl = ref<string>("");

const handlerTextChange = async (e: Event) => {
  if (!canvas.value) return;
  const target = e.target as HTMLInputElement;
  text.value = target.value;
  await QRCode.toDataURL(canvas.value, target.value);
  dataUrl.value = canvas.value.toDataURL();
}
</script>

<template>
  <div class="container">
    <input type="text" :value="text" @change="handlerTextChange"/>
    <canvas ref="canvas"></canvas>
    <a v-if="dataUrl" :href="dataUrl" download="qr.png">Download</a>
  </div>
</template>

<style scoped>
.container {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  width: 375px;
  margin: 0 auto;
  padding: 24px;
  text-align: center
}

canvas {
  display: block;
  margin: 0 auto;
}
</style>

こんな感じになります。

canvas 要素に描画

canvas 要素への描画は QRCode.toCanvas() を使用しても可能です。

toCanvas(canvasElement, text, [options], [cb(error)])
toCanvas(text, [options], [cb(error, canvas)])

Draws qr code symbol to canvas. If canvasElement is omitted a new canvas is returned. - qrcode - npm

その他

SVG 文字列を返す QRCode.toString() メソッドやサーバーサイドで使える QRCode.toFile() など便利なメソッドを具備しています。今回試してはいませんが、SJIS 対応しているようで、まだまだ SJIS に悩まされる日本の IT 業界には嬉しい対応です。

また各メソッドに共通してオプションを渡すことができます。詳細は こちら を参照してもらえればと思いますが、エラー訂正レベル等の QR コード自体のオプションや QR コードの色や余白等の見栄えに関するオプションが用意されています。

あとがき

qrcode パッケージを使用して QR コード生成をしてみました。qrcode はシンプルな API で非常に使いやすいです。今回は Vue で試しましたが、フロントのベースライブラリに依存しないので、React や Svelte でも使えるのがいいところです。機会があれば別ライブラリでも試してみようと思います。