今回はNode.js上で簡単にQRコードが生成できるnode-qrcode
を利用し、動的にQRコードを生成してみたいと思います。
github.com
QRコード自体は非常に便利ですよね。2次元バーコードよりも情報量が増やせるため様々な用途に利用できます。 しばらく前から日本はQRコード決済が世を賑わせていますが、個人的には早く滅んでくれないかなと思っていますがそれはまた別の話しw なんでFeliCaから退化しとんねんw
インストール
node-qrcode
はコマンドラインから利用できるコマンドも用意されていますが、今回はNode内からモジュールとして利用します。そのため適当なディレクトリを作成し、package.jsonを作った上で、npm install
してやります。
$ mkdir qr && cd qr; $ npm init $ npm install qrcode
HelloWorld
利用方法は実にシンプルで最短で2行書くだけです。1行目でモジュールを読み込み、2行目でQRコードを生成し画像として保存しています。
const QRCode = require('qrcode'); QRCode.toFile('foo.png', 'Hello QR');
コマンドラインから実行すると、foo.png
が作成されます。
$ node test.js
$ ls -l *.png -rw-r--r--@ 1 katsube staff 769 6 2 19:24 foo.png
実際に生成されたQRコードは以下です。スマホなどのQRコードリーダーで読み取ってみてください。
出力方式
BASE64
HTMLのimgタグ内に直接埋め込むために、BASE64でエンコードした形で出力することができます。
const QRCode = require('qrcode'); QRCode.toDataURL('Hello QR', function (err, url) { console.log(`<img src="${url}">`); });
以下のようなHTMLタグが出力されます。
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAAAAklEQVR4AewaftIAAAK6SURBVO3BQW7sWAwEwSxC979yjpdcPUCQusfmZ0T8wRqjWKMUa5RijVKsUYo1SrFGKdYoxRqlWKMUa5RijVKsUYo1SrFGKdYoFw8l4ZtUTpJwh8pJEr5J5YlijVKsUYo1ysXLVN6UhJMkdCpdEt6k8qYkvKlYoxRrlGKNcvFhSbhD5Q6VO1TelIQ7VD6pWKMUa5RijXLxj0tCp/KXFWuUYo1SrFEu/rgkdCqdSpeEyYo1SrFGKdYoFx+m8kkqT6g8ofKbFGuUYo1SrFEuXpaEb0pCp9IloVPpktCpnCThNyvWKMUapVijxB8MkoRO5V9SrFGKNUqxRrl4KAmdSpeETqVLQqfSJaFTOVG5Iwmdyh1J6FROktCpvKlYoxRrlGKNEn/wQBKeUOmS0KmcJKFTOUlCp9IloVN5UxJOVJ4o1ijFGqVYo1y8TOUkCV0SOpUuCd+kcpKE36xYoxRrlGKNEn/wQBKeUOmS0KmcJOGTVN6UhE7lTcUapVijFGuU+IMXJeGbVLok3KFykoROpUtCp/J/KtYoxRqlWKNcvEzlm5LQqXRJ6FTepHKShBOVNxVrlGKNUqxRLh5KwjepdCpdEu5IQqfSqXRJOFG5IwmdyhPFGqVYoxRrlIuXqbwpCXeodEk4UTlJwonKiUqXhE7lTcUapVijFGuUiw9Lwh0qdyThiSR0KicqXRI6lROVTyrWKMUapVijXPxxKl0STpLQqXRJ6FS6JNyRhBOVNxVrlGKNUqxRLv64JJyodEm4IwmdSpeEO1S6JHQqTxRrlGKNUqxRLj5M5ZNUuiTckYQTlSdUuiR0Km8q1ijFGqVYo1y8LAnflIRO5Q6VLgldEk5UnkhCp/JEsUYp1ijFGiX+YI1RrFGKNUqxRinWKMUapVijFGuUYo1SrFGKNUqxRinWKMUapVijFGuU/wDBCBfkDBM1EQAAAABJRU5ErkJggg==">
SVG
imgタグ以外にもSVGでの出力にも対応しています。
const QRCode = require('qrcode'); const options = { type: 'svg' }; QRCode.toString('Hello QR', options, function (err, str) { console.log(str); });
出力結果は以下。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 29 29" shape-rendering="crispEdges"><path fill="#ffffff" d="M0 0h29v29H0z"/><path stroke="#000000" d="M4 4.5h7m2 0h3m2 0h7M4 5.5h1m5 0h1m1 0h1m1 0h2m2 0h1m5 0h1M4 6.5h1m1 0h3m1 0h1m3 0h1m3 0h1m1 0h3m1 0h1M4 7.5h1m1 0h3m1 0h1m3 0h1m1 0h1m1 0h1m1 0h3m1 0h1M4 8.5h1m1 0h3m1 0h1m1 0h1m2 0h2m1 0h1m1 0h3m1 0h1M4 9.5h1m5 0h1m4 0h1m2 0h1m5 0h1M4 10.5h7m1 0h1m1 0h1m1 0h1m1 0h7M13 11.5h1M4 12.5h1m1 0h1m1 0h1m1 0h1m5 0h1m3 0h1m2 0h1M4 13.5h4m1 0h1m2 0h1m2 0h1m1 0h1m5 0h2M4 14.5h1m2 0h2m1 0h3m2 0h1m3 0h6M4 15.5h4m1 0h1m2 0h6m5 0h1M5 16.5h7m1 0h3m2 0h1m1 0h1M12 17.5h1m1 0h1m3 0h1m3 0h2M4 18.5h7m2 0h2m1 0h1m2 0h2m1 0h3M4 19.5h1m5 0h1m3 0h1m3 0h2m3 0h1M4 20.5h1m1 0h3m1 0h1m1 0h3m1 0h1m1 0h1m1 0h1M4 21.5h1m1 0h3m1 0h1m2 0h3m1 0h1m1 0h2m1 0h2M4 22.5h1m1 0h3m1 0h1m1 0h2m1 0h1m1 0h2m1 0h1m1 0h1m1 0h1M4 23.5h1m5 0h1m2 0h1m1 0h3m2 0h1m2 0h1M4 24.5h7m1 0h1m2 0h1m1 0h3m3 0h2"/></svg>
実際に表示させてみるとこんな感じです。サイズはCSSで調整してます。
文字列
おそらくコンソール画面などで表示するためのものだと思いますが、文字列でQRコードを取得できます。
const QRCode = require('qrcode'); const options = { type: 'terminal' }; QRCode.toString('Hello QR', options, function (err, str) { console.log(str); });
以下のような結果が得られます。
typeの値をutf8
にすると(指定を行わない場合のデフォルト値)、以下のような結果になりますが、こちらは私の環境だとQRコードリーダーが認識してくれなかったので、表示する際のフォントやら何やらをがんばらないとダメそうですね。
canvas
node-canvas
に出力することも可能です。HTML5から搭載されたcanvas要素がnode上でも利用できるという物ですが、別の画像を上に載せたり、QRコード自体に装飾をするなど加工が簡単にできるようになりますね。
github.com
node-canvas
は別途インストールする必要があります。
$ npm install canvas
ここでは最終的に画像データをBASE64に変換して出力しています。
const { createCanvas } = require('canvas'); const canvas = createCanvas(200, 200); const QRCode = require('qrcode'); const options = {}; QRCode.toCanvas(canvas, 'Hello QR', options, function(error){ // 文字を入れる const ctx = canvas.getContext('2d'); ctx.font = '20px Impact'; ctx.fillStyle = 'blue'; ctx.fillText('Hello!', 10, 20); console.log('<img src="' + canvas.toDataURL() + '" />'); });
出力結果は以下の通り。
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAAABmJLR0QA/wD/AP+gvaeTAAAFXUlEQVR4nO2dT2gUVxzHPxtz0IDSaBZMDRJacjBFRcFCEaSHoBJBQSGxPWhLLYgHFTx4K54iRQQFD/7FCi0txNpLYy2BEPASIQUxpIgSBKM5GpDUeNrXw5uQ3dl1d9/Mm8nOL78PLMP83r8Zvvt77/3e/MsZYwyKGJqW+gAUv6igwlBBhaGCCsNJ0OfPYXAQJiaq5xschHv3oh3Q+/e2/NjYom1szNrm56PVOT9vy9+/H618pjAOXL5sDBhz9uyH8xQKNk9Li0vNi8zM2PL9/Yu2w4et7fXraHVOT9vynZ3RymcJ7XKFoYIKoznNxt6+hdu3YXzc7m/bBkeOQFtbtPqePYPr12FyEnI52L4djh+Hjg5/x5w1UvPQiQno7obTp2FoCEZG4MwZ2LQJRkfd67t7FzZvhkuXYGYGXryAgQHbxoMHpXmbm0u3kol0io8fW8+oRKWFxLk5OHAAZmetEIcOWfvDh7B/Pxw8CFNT0NpaX/tTU3D0KLS3w/AwdHVZ+/g47N0LfX3We9evt/Z166wHr13rdp6ZxGUGtTDLredXPMu9csXazp8vr/PCBZt27Zrdr2eWe/Kk3b9zp7y+ixdt2sBAqb211ZjeXpezzSaRPLS/H44d+9AfBHbvLrUtdIG7dlkvLWbHDrutFdsWMzJiu8++vvK0PXtsV/7oUam9rc16qnQiCdrZCT09ldMqdbkvX9rtzp0frjMsdDVevbLd6cqV5Wn5fOX68vnok68skco0IZez25s3Yc2aynk2bHCrs1CobH/zxm5Xry615/PLw0NjrxQBoV8uGEf/K7L9Edg+r5D/IwM9Bj4J9tuDvL8V5fk1sH1sjDFm61ZjmpqMmZ0tP0b4Osj7Y6idbwx8WdZ+LcqPN9lfXFIKW/4Mtt9VSPsBGAa66q5t3z7roVevVkr9NtiGF5N/AkbrbiOrpBSZ/QycAL4HZoGhoOmvAtvfWFHr49QpuHULzp2Dpibo7YV37+DGDYAe4HegeFbUAUwD/wKfxT6bhsbFnaN3uRjIG/grFN4UDAwaaC3KV7vLNcaYJ0+M6e4uDZVyOWPgFwMtobY7gjyT4rvcXHDQkcktzHgW/yBV8z99akOUVatgyxbYuDF6/YUCrFjxBfApMAf8gzHTVcuHqXW8rufniu/6UxfUd/2u6WGkCapXW4Shggoj8VlurS4vjGuXk3T+WiR9fq6ohwpDBRWGCiqMZXANvzpJhyVpox4qDBVUGCqoMDI/htYaA12XArOOeqgwVFBhqKDCSHwMTTqui1v/Upf3jXqoMFRQYaigwvA+hqYd5/m+RcX1lpRGQz1UGCqoMFRQYcS+jbPRkHZ90xX1UGGooMJQQYUROw5NOg50HRNdx8y4Y27cONb3GK8eKgwVVBgqqDC8P07oiu+11bj50358MIw+TqiUoIIKQwUVhvfroa5jWNxH6n2j10OVhkIFFYYKKgxxcahvGv01NmHUQ4WhggpDBRWG93uKljpu9P3eoKVe+3VFPVQYKqgwVFBhpL6W65ulHuPixskahypVUUGFoYIKw/t9uUnj+z1Evt9zlPZ9wWHUQ4WhggpDBRVGw8ehcddmfX/mw7V82nGxeqgwVFBhqKDCyPx3W+LGwXGfP036+VVX1EOFoYIKQwUVRubfOe8adyb9+cpa7YXROFSpigoqDBVUGJkfQ13HKN/XS32vNev1UKUEFVQYKqgwxH23pdHiRL0eqsRCBRWGCioM8d9tqUWtMS7pMVbjUKUqKqgwVFBhiPtuy3JHPVQYKqgwVFBhqKDCUEGFoYIKQwUVhgoqDBVUGCqoMFRQYaigwlBBhaGCCkMFFcb/JCAhpAILP7YAAAAASUVORK5CYII=" />
実際に表示するとこのようになります。文字列Hello
が左上に入っています。
オプション
高さと横幅
第3引数に様々なオプションをハッシュで指定することができます。
width
に横幅のピクセル数を指定すると、そのサイズのQRコード(画像)が生成されます。
const QRCode = require('qrcode'); const options = {width:500}; QRCode.toFile('foo.png', 'Hello QR', options);
基本的にQRコードは正方形ですので、高さを指定する必要はありません。
色
color
にRGBを指定することで、QRコードや背景色を指定できます。
以下のコードではQRコードを白、背景が黒になります。
const QRCode = require('qrcode'); const options = { color: { dark: '#FFF', // QRコード light: '#000' // 背景 } }; QRCode.toFile('foo.png', 'Hello QR', options);
- 厳密にはRGBではなくRGBAとなっており、最後にアルファチャンネルの指定が可能です。
- デフォルトでは以下の指定がされています。
color.dark
が#000000ff
(QRコード)color.light
が#ffffffff
(背景)
以下のような出力結果になります。
背景を透過色
背景色color.light
で、アルファチャンネルの指定を行います。
const QRCode = require('qrcode'); const options = { color: { dark: '#000', // QRコード light: '#FFF0' // 背景(透過させる) } }; QRCode.toFile('foo.png', 'Hello QR', options);
以下のような出力結果になります。背景色をCSSで薄いピンクにしてあります。
余白
QRコード画像のマージンを指定できます。デフォルトは4です。
const QRCode = require('qrcode'); const options = { margin: 10 }; QRCode.toFile('foo.png', 'Hello QR', options);
最大文字数
「エラー訂正レベル」と「文字列の種類」によって、QRコードに埋め込める最大文字列長が変わってきます。
モード | L | M | Q | H |
---|---|---|---|---|
Numeric | 7,089 | 5,596 | 3,993 | 3,057 |
Alphanumeric | 4,296 | 3,391 | 2,420 | 1,852 |
Byte | 2,953 | 2,331 | 1,663 | 1,273 |
Kanji | 1,817 | 1,435 | 1,024 | 784 |
エラー訂正レベル
エラー訂正レベルのデフォルトはMですが、オプションによって指定することが可能です。
const QRCode = require('qrcode'); const options = { errorCorrectionLevel: 'M' // エラー訂正レベル(L, M, Q, H) }; QRCode.toFile('foo.png', 'Hello QR', options);
要はエラー訂正レベルが強いほど、たくさんの文字を埋め込めるというお話です。その代わりQRコードのサイズも大きくなります。
文字列の種類
通常、文字列の種類は自動的に判別されますが、手動で設定することができます。
モード | 文字種 | 圧縮 |
---|---|---|
Numeric | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 | 3文字を10bitに圧縮 |
Alphanumeric | 0–9, A–Z (大文字のみ), 半角スペース, $, %, *, +, -, ., /, : | 2文字を11bitに圧縮 |
Kanji | シフトJIS (JIS X 0208規格に基づく) | 2文字の漢字等を13bitに圧縮 |
Byte | ISO/IEC 8859-1に基づく文字 | 各文字は8bit |
以下のコードでいうと変数segment
に代入しているハッシュのように、文字列毎に種類を設定します。
const QRCode = require('qrcode'); const segment = [ { data:'ABCDEFG', mode:'alphanumeric' }, { data:'0123456', mode:'numeric' } ]; const options = {}; QRCode.toFile('foo.png', segment, options);
次のQRコードが生成されます。2つの要素が結合されているのが確認できます。
……まぁ基本的にはライブラリにお任せしちゃうのが良いですね。なにか特別な事情がある場合に利用する感じでしょうか。
UTF8を利用するには
結論から言うとByteモードにすれば、大抵のQRコードリーダーで読み取ることが可能です。特に設定する必要はありません。 (ただし1文字あたり最大4byteかかる点に注意)
詳しくはドキュメントを参照ください。
Multibyte characters Support for multibyte characters isn't present in the initial QR Code standard, but is possible to encode UTF-8 characters in Byte mode. QR Codes provide a way to specify a different type of character set through ECI (Extended Channel Interpretation), but it's not fully implemented in this lib yet. Most QR Code readers, however, are able to recognize multibyte characters even without ECI. Note that a single Kanji/Kana or Emoji can take up to 4 bytes.