勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

JavaScriptでWebカメラやスマホカメラを利用してQRコードを読み取りURLを返す方法

   2024/04/25  JavaScript

JavaScriptのjsQRというライブラリで簡単にWebページ版QRコードリーダーを作れるらしい。具体的にはPCのWebカメラやスマートフォンカメラでQRコードを読み取り、URLを返してくれるというもの。おもしろそうだったので以下に実装方法とサンプルをメモ。

 

jsQR

公式サイト

https://github.com/cozmo/jsQR

CDN

CDNで使う場合は以下を記述する。

<script src=" https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js "></script>

異なるバージョンを利用したい場合は以下から探す。

https://www.jsdelivr.com/package/npm/jsqr

 

サンプル

https://taitan916.info/sample/jsQR/

 

ソースコード

<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>jsQRのテスト</title>
<meta name="viewport" content=”width=device-width,initial-scale=1″>
<style>
body {
    color: #333;
    max-width: 640px;
    margin: 0 auto;
    position: relative;
}
#loadingMessage {
    text-align: center;
    padding: 40px;
    background-color: #eee;
}
#canvas {
    width: 100%;
}
#output {
    margin-top: 20px;
    background: #eee;
    padding: 10px;
    padding-bottom: 0;
}
#output div {
    padding-bottom: 10px;
    word-wrap: break-word;
}
#noQRFound {
    text-align: center;
}
</style>
</head>
<body>
    <div id="loadingMessage">
        ビデオストリームにアクセスできません(Webカメラが有効になっていることを確認してください)
    </div>
    <canvas id="canvas" hidden></canvas>
    <div id="output" hidden>
        <div id="outputMessage">QRコードが検出されませんでした</div>
        <div hidden><b>Data:</b> <span id="outputData"></span></div>
    </div>
    <script src=" https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js "></script>
    <script>
        var video = document.createElement("video");
        var canvasElement = document.getElementById("canvas");
        var canvas = canvasElement.getContext("2d");
        var loadingMessage = document.getElementById("loadingMessage");
        var outputContainer = document.getElementById("output");
        var outputMessage = document.getElementById("outputMessage");
        var outputData = document.getElementById("outputData");

        function drawLine(begin, end, color) {
            canvas.beginPath();
            canvas.moveTo(begin.x, begin.y);
            canvas.lineTo(end.x, end.y);
            canvas.lineWidth = 4;
            canvas.strokeStyle = color;
            canvas.stroke();
        }

        navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }).then(function(stream) {
            video.srcObject = stream;
            video.setAttribute("playsinline", true);
            video.play();
            requestAnimationFrame(tick);
        });

        function tick() {
            loadingMessage.innerText = "Loading video..."
            if (video.readyState === video.HAVE_ENOUGH_DATA) {
                loadingMessage.hidden = true;
                canvasElement.hidden = false;
                outputContainer.hidden = false;

                canvasElement.height = video.videoHeight;
                canvasElement.width = video.videoWidth;
                canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
                var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
                var code = jsQR(imageData.data, imageData.width, imageData.height, {
                    inversionAttempts: "dontInvert",
                });
                if (code) {
                    drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
                    drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
                    drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
                    drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
                    outputMessage.hidden = true;
                    outputData.parentElement.hidden = false;
                    outputData.innerText = code.data;
                } else {
                    outputMessage.hidden = false;
                    outputData.parentElement.hidden = true;
                }
            }
            requestAnimationFrame(tick);
        }
    </script>
</body>
</html>

ソースコードはデモサイトのものをほぼ流用。

 

考えられる使いどころ

スマホでQRコードを読み込ませてブラウザで開いたりクリップボードにコピーしたりというのは通常のアプリの方が良いので、それ以外の部分で使うことになる。

具体的にはURLをスプレッドシートやデータベースに書き込むとか。例えば書籍とかチラシとかでたまにQRコードが載っており「できればPCで閲覧したいんだけど……」といった時に通常のアプリだと「読み取り→何らかの方法でURLをPCに送信→PC側のブラウザで開く」となるが、スプレッドシートに自動で書き込んだ場合「何らかの方法でPCに送信」部分が不要になる。

無理やりひねり出した感があり実用性にはかけそう。

 

所感

JavaScriptでQRコードを読み取れる、というのは面白いんだけど、QRコードは通常のスマホアプリである程度問題無いため使いどころが難しく感じた。

尚、QuaggaJSというライブラリだと通常のバーコードが読み込めるらしく、こちらならもうちょっと使いどころがありそう。その内試してみたいところ。

 - JavaScript

  関連記事

JavaScriptでtableタグをエクセルファイル(xlsx)としてダウンロードさせる方法

table内のデータを何らかのファイルでダウンロードさせたい。通常PHPでCSV ...

円形のプログレスバーをprogressbar.jsで実装する方法

円形のプログレスバーを実装したかった。CSSだったり画像を用いたりする方法もあっ ...

JavaScriptで小数の計算をする際にずれ(誤差)を無くす方法(decimal.js)

JavaScriptで小数の計算をすると値がずれる(誤差が発生する)ことがあった ...

JavaScriptにて領収書等のテンプレートHTMLページをPDFファイル化させる方法(html2pdf)

JavaScriptにてhtml2pdfというライブラリを使用することでHTML ...

表示範囲を自由に変更可能な折れ線グラフが表示できるJSライブラリ amCharts の使用方法

どこかのサイトを閲覧していた際に、恐らくはJavaScriptのライブラリで描写 ...