jsQR+αでかんたんQRコードリーダ/メーカ
QRコードリーダ/メーカを作る
2つのライブラリを同時に使い、QRコードリーダ/メーカを作ってみます。
今回は、"localhost"環境での実働テストを試してみます。
ライブラリ | 用途 |
---|---|
jsQR | QRコードを検出します |
qrcode | QRコードを生成します |
実際にインターネットに公開する場合、"https"環境が整っているサーバーが必要になりますので注意しましょう。
QRコードリーダーを作る
jsQRを利用する事で、とても簡単にQRコードリーダーを作る事ができます。
ライブラリのダウンロード
jsQRを、GitHubからダウンロードします。
ダウンロードした圧縮ファイルを解凍します。
解凍したフォルダ中にある"jsQR.js"がライブラリ本体です。
プロジェクトを作る
次の様にプロジェクトを作ります。
MyProject01/
├ custom.css (スタイルを記述するファイルです)
├ index.html (プログラムを起動するファイルです)
├ main.js (メインのプログラムを記述するファイルです)
├ jsQR.js (ライブラリの本体ファイルです)
HTMLファイルを用意する
では、作っていきましょう。
HTMLファイルを用意して、下記コードを記述します。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- CSS -->
<link rel="stylesheet" href="./style.css"/>
<!-- JavaScript -->
<script src="./jsQR.js" defer></script>
<script src="./main.js" defer></script>
</head>
<body>
<h1>jsQR</h1>
<div id="wrapper">
<div id="msg">Unable to access video stream.</div>
<canvas id="canvas"></canvas>
</div>
</body>
</html>
"msg"エレメントには検出されたQRコードの内容を表示します。
そして、"canvas"エレメントには、Webカメラの画像が描画されます。
CSSファイルを用意する
次はCSSファイルです。
こちらは特に説明することはありませんね。
/* CSS */
body{
background-color: gray;
}
h1{
text-align: center;
}
#wrapper{
margin: 0px auto 0px auto;
width: 320px; height: auto;
}
#msg{
margin: 0px; padding: 10px;
background-color: lightgray;
text-align: center;
}
#canvas{
width: 100%; height: auto;
background-color: silver;
}
JavaScriptファイルを用意する
メインのプログラムを作っていきます。
全体の流れは次の通りです。
- Webカメラを起動する
- キャンバスに描画する
- QRコードを判定する
Webカメラを起動する
Webカメラを起動します。
Webカメラへのアクセスは、"getUserMedia"関数を実行します。
Webカメラの起動に成功すると、"then"関数が実行されます。
カメラの準備が出来たタイミングで、"startTick"関数を実行して次の処理に進みます。
// 省略
const userMedia = {video: {facingMode: "environment"}};
navigator.mediaDevices.getUserMedia(userMedia).then((stream)=>{
video.srcObject = stream;
video.setAttribute("playsinline", true);
video.play();
startTick();
});
// 省略
キャンバスに描画する
"drawImage"関数を実行し、Webカメラからのデータをキャンバスに描画します。
引数には"video"オブジェクト、そして描画エリアの開始点と終了点の座標を指定します。
// 省略
function startTick(){
msg.innerText = "Loading video...";
if(video.readyState === video.HAVE_ENOUGH_DATA){
canvas.height = video.videoHeight;
canvas.width = video.videoWidth;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
// このタイミングでQRコードを判定します
}
setTimeout(startTick, 250);
}
// 省略
QRコードを判定する
いよいよQRコードの判定処理です。
判定対象であるイメージデータは、"getImageData"関数を使って取得します。
その後、取得したイメージデータを"jsQR"関数に渡します。
"jsQR"関数の実行結果が"null"でなければ、検出が成功している状態です。
"null"だった場合は検出失敗(未検出)になります。
検出成功時、"code.location"には、検出された座標データが、
"code.data"には、QRコードで取得した文字列データが格納されています。
具体的には次の様な記述になります。
// 省略
let img = ctx.getImageData(0, 0, canvas.width, canvas.height);
let code = jsQR(img.data, img.width, img.height, {inversionAttempts: "dontInvert"});
if(code){
drawRect(code.location);// 検出されたQRコードの位置を描画します
msg.innerText = code.data;// 検出されたQRコードの文字列データを表示します
}else{
msg.innerText = "Detecting QR-Code...";
}
// 省略
全体のコード
ここまでのコードを載せておきますね。
window.onload = (e)=>{
let video = document.createElement("video");
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let msg = document.getElementById("msg");
const userMedia = {video: {facingMode: "environment"}};
navigator.mediaDevices.getUserMedia(userMedia).then((stream)=>{
video.srcObject = stream;
video.setAttribute("playsinline", true);
video.play();
startTick();
});
function startTick(){
msg.innerText = "Loading video...";
if(video.readyState === video.HAVE_ENOUGH_DATA){
canvas.height = video.videoHeight;
canvas.width = video.videoWidth;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
let img = ctx.getImageData(0, 0, canvas.width, canvas.height);
let code = jsQR(img.data, img.width, img.height, {inversionAttempts: "dontInvert"});
if(code){
drawRect(code.location);// Rect
msg.innerText = code.data;// Data
}else{
msg.innerText = "Detecting QR-Code...";
}
}
setTimeout(startTick, 250);
}
function drawRect(location){
drawLine(location.topLeftCorner, location.topRightCorner);
drawLine(location.topRightCorner, location.bottomRightCorner);
drawLine(location.bottomRightCorner, location.bottomLeftCorner);
drawLine(location.bottomLeftCorner, location.topLeftCorner);
}
function drawLine(begin, end){
ctx.lineWidth = 4;
ctx.strokeStyle = "#FF3B58";
ctx.beginPath();
ctx.moveTo(begin.x, begin.y);
ctx.lineTo(end.x, end.y);
ctx.stroke();
}
}
これだけでQRコードリーダーができてしまいます。(やりました!!)
QRコードメーカーを作る
公式サイトよりライブラリをダウンロードし、解凍したフォルダにある"qrcode.js"をプロジェクトに追加します。
プロジェクトは次の様になります。
MyProject01/
├ custom.css (スタイルを記述するファイルです)
├ index.html (プログラムを起動するファイルです)
├ main.js (メインのプログラムを記述するファイルです)
├ jsQR.js (ライブラリの本体ファイルです)
├ qrcode.js (ライブラリの本体ファイルです)
HTMLファイルを編集する
先程のHTMLに、QRコードを表示するエリアを用意します。
"qrcode.js"ライブラリの読み込みと、idが"qrcode"となっている"div"タグを追加します。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- CSS -->
<link rel="stylesheet" href="./style.css"/>
<!-- JavaScript -->
<script src="./jsQR.js" defer></script>
<script src="./qrcode.js" defer></script>
<script src="./js/main.js" defer></script>
</head>
<body>
<h1>jsQR</h1>
<div id="wrapper">
<div id="msg">Unable to access video stream.</div>
<canvas id="canvas"></canvas>
<div id="qrcode"></div>
</div>
</body>
</html>
JavaScriptファイルを編集する
QRコードを生成するパターンは次の通りです。
次のコードを見てもらうとわかる通り、とてもシンプルに記述する事ができます。
第一引数の"qrcode"は、HTMLの表示先のidです。
let qrcode = new QRCode("qrcode", {
text: text,
width: 128, height: 128,// QRコードの幅と高さ
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
});
全体のコード
最後に全体のコードを載せておきますね。
window.onload = (e)=>{
let video = document.createElement("video");
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let msg = document.getElementById("msg");
const userMedia = {video: {facingMode: "environment"}};
navigator.mediaDevices.getUserMedia(userMedia).then((stream)=>{
video.srcObject = stream;
video.setAttribute("playsinline", true);
video.play();
startTick();
});
function startTick(){
msg.innerText = "Loading video...";
if(video.readyState === video.HAVE_ENOUGH_DATA){
canvas.height = video.videoHeight;
canvas.width = video.videoWidth;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
let img = ctx.getImageData(0, 0, canvas.width, canvas.height);
let code = jsQR(img.data, img.width, img.height, {inversionAttempts: "dontInvert"});
if(code){
drawRect(code.location);// Rect
msg.innerText = code.data;// Data
makeQR(code.data);// QRCode
}else{
msg.innerText = "Detecting QR-Code...";
}
}
setTimeout(startTick, 250);
}
function drawRect(location){
drawLine(location.topLeftCorner, location.topRightCorner);
drawLine(location.topRightCorner, location.bottomRightCorner);
drawLine(location.bottomRightCorner, location.bottomLeftCorner);
drawLine(location.bottomLeftCorner, location.topLeftCorner);
}
function drawLine(begin, end){
ctx.lineWidth = 4;
ctx.strokeStyle = "#FF3B58";
ctx.beginPath();
ctx.moveTo(begin.x, begin.y);
ctx.lineTo(end.x, end.y);
ctx.stroke();
}
function makeQR(text){
document.getElementById("qrcode").innerHTML = "";// Clear
let qrcode = new QRCode("qrcode", {
text: text,
width: 128, height: 128,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
});
}
}
判別したQRコードをそのまま生成できている事が確認できます。(やりました!!)
最後に
簡単にQRコードリーダーが出来る事が伝わったかと思います。
QRコード自体は昔からある見慣れた存在ですが、改めて見直してみるとアイデアが出るかもしれませんね。
繰り返しになりますが、インターネット上での利用には"https"環境でのサーバーが必要になりますのでご注意くださいませ。
ここまで読んでいただき有難うございました。
Discussion