🌿 えふてぃブログ

個人ブログにQRフォトメーカーを作った話【つまずきポイントと解決まで】


📑 目次

こんにちは、えふてぃです。

「ブログって、記事を書くだけじゃなくて、何か使えるものも置けたら面白そうだな」

そんなことを考えて早速、個人ブログに ツールページ を作ってみました。
最初に作ったのは「QRフォトメーカー」という、背景写真の上にQRコードを半透明で重ねて、写真が透けて見えるQRコードを生成できるWebツールです。

きっかけの一つは、技術イベントに参加したときの体験ですね。
会場のWi-Fi情報がホワイトボードや紙に書いてあって、一文字ずつ打ち込む…あれ、地味に面倒だなぁと感じてました。
ならこれQRにしたら良くね?って思って作ってみました。

この記事では、企画から実装、そして直した点を中心に振り返ります。

まずはQRフォトメーカーとは何か

QRフォトメーカーは、ブラウザ上で完結するQRコード生成ツールです。

普通のQRコードって、白と黒の四角が並んだだけでもう少し遊びが欲しいなぁと思っていたので、 このツールでは、背景に好きな写真や色を設定して、その上にQRコードを半透明で重ねることで、 写真が透けて見えるQRコード を作れます。

主な機能はこんな感じです。

  • URLモード: URLを入力すると、スキャンでWebサイトに遷移するQRコードを生成
  • Wi-Fiモード: SSID・パスワード・暗号化方式を入力すると、スキャンでWi-Fiに自動接続
  • 背景設定: 画像アップロード、単色、グラデーションの3種類から選択
  • カスタマイズ: ドットの色、QRサイズ、透過度、マージンを自由に調整
  • PNG / JPG ダウンロード対応

技術スタックと設計判断

技術スタックは以下の通りです。

項目選定
フレームワークAstro(既存ブログサイトに組み込み)
言語TypeScript
QR生成qr-code-styling
画像合成Canvas API(ブラウザ標準)
処理方式全てクライアントサイド完結
📝 検証環境

Astro 5.x / qr-code-styling 1.9.2 で動作確認しています。

QR生成ライブラリは EasyQRCodeJSQRCode.js などいくつか候補がありましたが、最終的に qr-code-styling にしました。
決め手は、コミュニティが大きくて情報が見つかりやすいことと、透明背景が公式でサポートされていて「これなら写真との合成もやりやすそうだな」という判断です。

もう一つこだわったのは、 処理を全てブラウザ内で完結 させたことです。
そもそもAstroはコンテンツ駆動のフレームワークなので、現状はDBやバックエンドは持ちたくない。それに、Wi-FiモードではSSIDやパスワードを扱うので、サーバーにデータが飛ばない方がプライバシー的にも安心。
開いてすぐサッと使えるツールにしたかったので、クライアント完結で進めました。

実装のポイント:半透明QRと背景合成

このツールの核心は「半透明のQRドットを写真の上に重ねる」部分です。

qr-code-stylingの dotsOptions.color にrgba文字列を渡せば半透明ドットになるか、正直やってみるまでわかりませんでした。
結果的にはrgbaであっさりいけたので、実装はシンプルに収まりました。

const rgbaColor = `rgba(${r}, ${g}, ${b}, ${opacity})`;

const qrCode = new QRCodeStyling({
  dotsOptions: {
    color: rgbaColor, // rgbaで半透明ドットが実現できた
    type: 'rounded',
  },
  backgroundOptions: {
    color: 'transparent', // 背景は透明に
  },
  qrOptions: {
    errorCorrectionLevel: 'H', // 背景と合成するので最高レベルに
  },
});

合成の流れは、qr-code-stylingで透明背景のQRを生成 → Canvasに背景を描画 → その上にQRを重ねる、というシンプルなものです。

💡 誤り訂正レベルはHが必須

背景との合成ではQRドットの一部が見えにくくなるため、誤り訂正レベルは最高の 'H' に設定しています。
これにより約30%のデータ欠損に耐えられます。透過度を下げすぎると読み取れなくなるので、最低値にも制限をかけています。

つまずきポイント:Wi-Fiモードの落とし穴

Wi-Fiモードでは、入力されたSSIDとパスワードから WIFI:T:WPA;S:MySSID;P:password;; という形式の文字列を生成してQRコードにします。

ところが、パスワードに ;:" などの特殊文字が含まれていると、QRコードのWi-Fi情報のフォーマットが壊れてしまいます。
パスワードに特殊文字を使うのはよくあることなので、ここは対応が必須でした。

対策として、Wi-Fi QRコードの仕様で定められた特殊文字をエスケープする関数を追加しました。

function escapeWifiValue(value: string): string {
  return value.replace(/([\\;,:"'])/g, '\\$1');
}

function getQRData(): string {
  if (currentMode === 'wifi') {
    const ssid = escapeWifiValue(ssidInput.value);
    const password = escapeWifiValue(passwordInput.value);
    const encryption = encryptionSelect.value;
    return `WIFI:T:${encryption};S:${ssid};P:${password};;`;
  }
  return urlInput.value;
}

UXを良くするのが地味に大変だった

技術的な問題を解決した後、一番時間がかかったのが UXの改善 でした。

マージンUIの変遷

QRコード周囲の余白(マージン)の調整は、最初スライダーにしていたのですが、細かい数値を触らせてもユーザーには意味がない。
ということで最終的に 「なし / 小 / 大」の3択ボタンに落ち着きました。
Webツールとしてサッと使ってもらうには、選択肢を絞って迷わせないことが大事そうですね。

WEP削除の判断

Wi-Fiの暗号化方式は、最初「WPA/WPA2」「WEP」「なし」の3択で作っていました。
ただ、私自身WEPが何なのかよくわからなくて、調べてみたら過去に脆弱性が見つかって以降、今はほぼ使われていないらしい。

なので削って「WPA/WPA2(推奨)」「なし(フリーWi-Fi)」の2択に絞りました。

QR未入力時の「壊れてる?」問題

背景画像を設定したのにURLをまだ入力していないと、プレビューが真っ白のままでした。
ユーザーからすると「背景画像を設定したのに何も表示されない…壊れてる?」という不安になります。

対策として、 QRデータ未入力でも背景だけはプレビューに表示 されるようにしました。
「ちゃんと背景は設定できていますよ」という安心感を与える、地味だけど大事な改善でした。

ちなみにこの状態ではQRコード自体は生成されていないので、ダウンロードボタンも無効のままにしています。

まとめ:個人ブログにツールを作る楽しさ

個人ブログに「使えるツール」を置くのは、なかなか面白いので今後も何かしら作っていこうかと思います。 もちろん想定ユーザを考えて作成しないとではあるが。

それと今回の開発で特に学んだのは以下のポイントです。

  • Webツールは ユーザーが一目で迷わない形 にすることが大事(細かい数値のスライダーより3択ボタン、など)
  • 使われていない規格や選択肢は事前に調べて除いておく(ユーザーを混乱させないため)

興味がある方は、ぜひ QRフォトメーカー を試してみてください。


このブログが面白いと思った方は、是非とも下のボタンをクリックして、記事シェアやフォローをしていただけると嬉しいです!