この記事は最終更新日から1年以上が経過しています。
@programming
投稿日 2019/6/25
更新日 2019/6/25 ✏
ブラウザでQRコード読込と生成
ブラウザでQRコードを読み込んで解析したり、QRコード画像を生成したりする方法のメモです。 今回のコードは、2019/06/25時点でおそらく最新のChromeブラウザ (v75.0.3770.100) とFifeFox (v67.0.3) で正常に動くことを確認しております。IEでは試してません笑。
目次
QRコードの読込
まずはQRコードを読み込みにはjsQRモジュールを利用します:
<script src="https://cdn.jsdelivr.net/npm/jsqr@1.1.1/dist/jsQR.min.js" integrity="sha384-i4Tuh5Z0ns/3M0289mSougur8irvedWPBlwOcJ7ob5AK/rvN5tjkwzu7P1k1dThG" crossorigin="anonymous"></script>
<!-- jqueryもロード。 NOTE: QRコード処理自体には無関係です。 -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
画像ファイルから読込
QRコード画像選択のファイルinput
要素を設置:
<input type="file" accept="image/png,image/jpg,image/jpeg,image/gif" onchange="scan(event)">
ファイルinput
要素で入力されたQRコード画像ファイルを読み込み、解析文字列をコンソール出力する処理:
function scan(e) {
const files = e.target.files || e.dataTransfer.files;
if (!files.length) return;
const file = files[0];
const fileReader = new FileReader();
fileReader.onload = function(theFile) {
const image = new Image();
image.onload = function() {
// create a canvas in memory:
const canvas = document.createElement('canvas');
// canvas needs enough width and height to draw the qrcode image:
canvas.width = this.width;
canvas.height = this.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
const imageData = ctx.getImageData(0, 0, this.width, this.height);
const data = jsQR(imageData.data, imageData.width, imageData.height);
if (data) {
const message = data.data;
console.log("message:", message); // message: "あいうえお"
}
};
const dataURL = theFile.target.result;
if (!dataURL || !dataURL.startsWith("data:image/")) {
alert("[ERROR] 読み取りできませんでした。");
}
image.src = dataURL;
};
fileReader.readAsDataURL(file);
}
Webカメラから読込
Webカメラ起動用のbutton
要素、Webカメラ用のvideo
要素、そしてスナップショット画像一時保存用のcanvas
要素を設置:
<button type="button" onclick="openWebcam(event)">Webカメラ起動</button>
<div id="pane-webcam">
<video name="video" style="max-height:300px; display: none;" autoplay></video>
<canvas name="canvas" style="max-height: 300px; display: none;"></canvas>
</div>
Webカメラ起動処理、カメラからのストリーム画像処理、Webカメラの停止処理:
// Webカメラの起動&ストリーム読込開始処理
function openWebcam(e) {
// related elements:
const $root = $("#pane-webcam");
const canvas = $root.find("[name=canvas]")[0];
const video = $root.find("[name=video]").show()[0];
const ctx = canvas.getContext('2d');
// open webcam device
navigator.mediaDevices.getUserMedia({
audio: false,
video: true,
}).then(function(stream) {
video.srcObject = stream;
video.onloadedmetadata = function(e) {
video.play();
self.snapshot({ video, canvas, ctx, });
};
}).catch(function(e) {
alert("ERROR: Webカメラの起動に失敗しました: " + e.message);
});
}
// 読み込んだストリームからスナップショットを取得&解析
function snapshot({ video, canvas, ctx, }) {
const self = this;
if (!video.srcObject.active) return;
// Draws current image from the video element into the canvas
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = jsQR(imageData.data, imageData.width, imageData.height);
if (!data) {
// QRコードのスナップショット画像を解析できるまでリトライ・・・
setTimeout(() => {
return self.snapshot({ video, canvas, ctx, }); // retry ...
}, 800); // NOTE: ここを小さくしすぎるとCPUに負荷が掛かります
} else {
// 解析成功!
if (data) {
const message = data.data; // QRコードからメッセージを取得
console.log("message:", message);
}
// Webカメラの停止
self.stopWebcam({ video, canvas, ctx, });
}
}
// Webカメラの停止処理
function stopWebcam({ video, canvas, ctx }) {
const self = this;
if (!video) {
video = $("[name=video]")[0];
}
video.pause();
stream = video.srcObject;
// self.stream.getVideoTracks()[0].stop();
stream.getTracks().forEach(track => track.stop());
video.src = "";
$(video).hide();
}
QRコードの生成
QRコードの生成にはnode-qrcodeモジュールを利用します:
<script src="https://cdn.jsdelivr.net/npm/qrcode@1.3.2/build/qrcode.min.js" integrity="sha256-I8UYV49P3IKHrVzMUvI9RLtciRSLE0E6oQv1rFM1OOM=" crossorigin="anonymous"></script>
QRコード画像を表示するimg
要素を設置:
<img id="qrcode" src="" />
"https://memo.appri.me/"
という文字列をQRコード化したDataURLを取得し、img
要素のsrc
属性にセットすることでQRコードが画面に表示されます:
QRCode.toDataURL("https://memo.appri.me/", function(err, dataurl) {
if (err) {
alert(err.message);
return;
}
console.log("result:", dataurl); // "data:image/png;base64,iVBORw..."
// img要素にDataURLをセット:
document.querySelector("#qrcode").setAttribute("src", dataurl);
});
ブラウザで使うメリット
jsQRやqrcodeモジュールはもちろんNode.jsでも使えます。ですが、せっかくブラウザでもここまで出来るのであれば、そこそこ負荷の掛かるQRコード読込&生成処理は全てブラウザ側に任せた方がサーバリソース的にもメリットがあると思います。
ひとこと
芽萌丸ツールズのQRコードツールというサービスは、今回のQRコード処理の参考になると思います。
以上です。