キャンバスを使ってバーコードの付いた帳票を印刷したい。
バーコードライブラリはいろいろ落ちているけど、うちはCODE39以外は使用しないので毎回大きなライブラリを読むのもったいない。
バーコードの仕組み自体はフォント化できるほど単純なので、勉強も兼ねて自分でバーコード関数を書いてみました。
バーコードの規格は小林クリエイト株式会社さまの「CODE39 基礎知識」を参考にしました。
テストコード
<html>
<head>
<style>
#canvas {
/*キャンバスのサイズ*/
width: 800px;
height: 400px;
/*描画のレンダリング方法*/
image-rendering: pixelated;
}
</style>
<script>
//キャラクタパターン情報
var pattern = {
'0':0xB65,'1':0xD4B,'2':0xD4D,'3':0xA9B,'4':0xD65,'5':0xACB,'6':0xACD,'7':0xDA5,'8':0xB4B,
'9':0xB4D,'A':0xD2B,'B':0xD2D,'C':0xA5B,'D':0xD35,'E':0xA6B,'F':0xA6D,'G':0xD95,'H':0xB2B,
'I':0xB2D,'J':0xB35,'K':0xCAB,'L':0xCAD,'M':0x95B,'N':0xCB5,'O':0x96B,'P':0x96D,'Q':0xCD5,
'R':0x9AB,'S':0x9AD,'T':0x9B5,'U':0xD53,'V':0xD59,'W':0xAB3,'X':0xD69,'Y':0xAD3,'Z':0xAD9,
'-':0xDA9,'.':0xB53,' ':0xB59,'$':0xA49,'/':0x949,'+':0x929,'%':0x925,'*':0xB69};
//jQueryで言う $(document).ready() のネイティブコード
document.addEventListener('DOMContentLoaded', function() {
//バーコード化するデータ(先頭と末尾はスタート・ストップキャラ)
var code_str = "*12345678*";
//バーの幅
var bar_width = 4;
//キャンバスのコンテキストを取得
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.lineWidth = bar_width;
context.lineCap = "butt";
context.strokeStyle = "black";
context.font = "20px sanserif";
context.setTransform(1, 0, 0, 1, 4, 0); //描画開始位置を右に4ピクセル移動するおまじない
context.beginPath();
for(var pos = 0; pos < code_str.length; pos++){
//一文字ずつ読み込み
var key = code_str.charAt(pos);
//パターン情報を読み込む
if(!pattern[key]) continue;
var pat = pattern[key];
//キャラクタごとの描画位置
//文字位置 * (12ビット + キャラクタ間ギャップ) x バー幅
var left = pos * (12 + 1) * bar_width;
//2進数12ビットのパターン情報を1ビットずつ走査してバーを描画
for(var i=0; i<12; i++){
//ビットが1ならバー描画
if( (pat & (1<<i)) > 0 ){
//バーの X座標
var x = i * bar_width + left;
//バー描画
context.moveTo(x, 0);
context.lineTo(x, 100);
}
}
//データの文字列を直接描画
context.fillText(key, left + bar_width * 6, 120);
}
//描画情報を反映
context.stroke();
});
</script>
</head>
<body>
<!--キャンバス-->
<canvas id="canvas" width="800" height="400"></canvas>
</body>
</html>
##キャラクタパターンについて
キャラクタパターンは、参考サイトを見ながら2進数化し、ビット演算がシンプルになるよう、逆順に並び替えた後に16進数化しています。
var pattern = ["101101100101", "110100101011", "101100101011", "110110010101"...];
var keys = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*";
var new_pattern = {};
for(let pat of pattern){
pat = pat.split("") //配列化
.reverse() //逆順化
.join(); //再度文字列化
pat = "0x" + parseInt(pat, 2).toString(16); //16進数化
new_pattern[keys.charAt(new_pattern.length)] = pat; //キーと組み合わせてハッシュ化
}
for...of に違和感! of じゃなくin にして欲しかった
逆順化がめんどくさいなら単純に2進数文字列にして、charAt()で一文字ずつ読み込むんでもいいと思います。(ただしデータ量は4倍になります)