猫の手ツール

Algorithm & Canvas Composition

デザインと読み取り精度を両立する
QRコード合成のハック

「QRコードの中央に猫を置きたい」という直感的なニーズを支えるのは、Canvas APIによる多層描画と、QRコードの数学的な復元能力の最大活用です。

1. 誤り訂正レベル「H」による情報の欠損補完

QRコードには一部が汚れたり隠れたりしてもデータを復元できる「誤り訂正機能」が備わっています。本ツールでは、中央にアイコンを合成することを前提としているため、このレベルを最高設定の Level H に固定しています。

これにより、QRコード全体の約30%が隠れても理論上は読み取りが可能です。あえて最高レベルを選択することで、デザインの自由度(アイコンのサイズ感)と、実用的なスキャン精度をトレードオフさせずに実装しています。

// QRコード生成のパラメータ最適化
await QRCode.toCanvas(tempCanvas, text, {
    // 誤り訂正レベルを最高(H)に固定することで
    // 中央のアイコン合成によるデータ欠損を許容する
    errorCorrectionLevel: 'H',
    width: QR_SIZE_CONST,
    color: {
        dark: selectedColor,
        light: "#ffffff"
    }
});

2. Canvasを用いた「背景マスク付き」重層描画

単純にQRコードの上に絵文字を重ねるだけでは、QRのドットパターンと絵文字が干渉し、視認性が著しく低下します。本ツールでは、アイコンの下に「白い円形の背景」を一段挟むことで、アイコンの輪郭を明確にし、同時にQRコードの読み取りセンサーが「ここはデータではなくノイズ(無視して良い場所)」と判断しやすくしています。

また、Canvasの ctx.save()ctx.restore() を活用し、アイコン描画時のみ影(shadow)を適用することで、フラットなQRコードの中でアイコンだけが浮き上がるようなUXを実現しています。

// アイコンの合成処理(概念コード)
function drawDecoratedIcon(ctx, centerX, centerY) {
    const iconAreaSize = // 独自の比率で算出
    
    ctx.save();
    
    // 1. 背面に白い円形を描画してQRドットを隠蔽
    ctx.beginPath();
    ctx.arc(centerX, centerY, iconAreaSize / 2, 0, Math.PI * 2);
    ctx.fillStyle = '#ffffff';
    ctx.fill();

    // 2. アイコン(Emoji)の描画設定
    ctx.font = `bold ${/* チューニングされたフォントサイズ */}px sans-serif`;
    
    // 3. 視認性を上げるための独自の影処理
    ctx.shadowColor = 'rgba(0, 0, 0, 0.15)';
    ctx.shadowBlur = // 動的なしきい値
    
    ctx.fillText(selectedIcon, centerX, centerY);
    
    ctx.restore();
}

Developer's Note

このツールで一番こだわったのは、「リアルタイム性」です。ユーザーがURLを一文字入力するたびに、裏側ではオフスクリーン・キャンバスでQRコードを再生成し、アイコンを合成し、最終的なプレビュー用のImage要素にデータを流し込んでいます。

一見重そうな処理ですが、最新のブラウザのCanvas APIは非常に高速で、800px四方の高解像度出力であっても、人間が遅延を感じないレベルで再描画が可能です。複雑なライブラリに頼りすぎず、Canvasという標準の武器を使い倒すことで、軽量かつ高機能なツールに仕上げることができました。