WebサイトからカメラでQRコードを読み取る – Android、iOS、PC対応 (ちょっとだけ改良版)

投稿者: | 2018年7月11日

こちらに完全版を投稿しています。

前に同じ内容で記事を投稿していましたが、今回は少し改善したバージョンです。改善といっても、カメラ情報を取得するための InstaScan を使用しないようにしたのと、iOSのカメラオプションを修正しただけです。

このコードを動かすには、以下の条件が前提となっています。

  • QRコードの情報を読み取るのに、次のライブラリーを使用しています。
    LazarSoft/jsqrcode https://github.com/LazarSoft/jsqrcode
     
    ただし、実際に使用しているのは上記ライブラリーを使いやすく改変したものです。改変したライブラリーは以下にあります。ページ末尾の最小化済みライブラリーをダウンロードしてください。
    ネイティブアプリ不要!モバイルWebサイトにQRコードリーダーを実装する方法
     
  • iOSで動作させる場合、iOS 11 以上が必須条件です。
  • iOSで使用できるブラウザは、Safari だけです。
  • PCで動作させる場合、当たり前ですが、Web対応のカメラが接続されている必要があります。
  • インターネット上でカメラを動作させるには、サイトが https であることが必須条件です。

コード例

index.html

<!doctype html>
<html lang="ja">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, intial-scale=1, mininum-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no"
    />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
</head>

<body>
    <h1>QRコード読み取りデモ2</h1>
    <div style="text-align: center;">
        <video id="video" style="width: 80%; height: auto;" autoplay playsinline></video>
    </div>
    <img id="img" />
    <div style="display: none;">
        <canvas id="canvas"></canvas>
    </div>
    <div>
        <input type="text" id="qr" value="">
    </div>
    <div>
        <button type="button" id="changeCamera">カメラ切り替え</button>
    </div>
    <div>
        <h2>アクティブなカメラ</h2>
        <p id="active-camera"></p>
    </div>
</body>

<script src="./js/qr/qr_packed.js" charset="UTF-8"></script>
<script type="text/javascript">
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
    alert('このブラウザーは非対応です');
    exit();
}

var ios = /iPad|iPhone|iPod/.test(navigator.userAgent);
var devices;
var activeIndex;
var iosRear = false;

// カメラ情報取得
navigator.mediaDevices.enumerateDevices()
    .then(function(cameras) {
        var cams = new Array();
        cameras.forEach(function(device) {
            if (device.kind === 'videoinput') {
                cams.push({
                    'id': device.deviceId,
                    'name': device.label
                });
            }
        });

        devices = cams;
        var c = new Array();
        for (var i = 0; i < cams.length; i++) {
            c.push('カメラ名: ' + cams[i].name);
            c.push('カメラID: ' + cams[i].id);
        }

        changeCamera(devices.length - 1);
    })
    .catch(function (err) {
        alert('カメラが見つかりません');
    });

var video = document.getElementById('video');
var localStream = null;

function decodeImageFromBase64(data, callback) {
    qrcode.callback = callback;
    qrcode.decode(data);
}

document.getElementById('changeCamera').addEventListener('click', function () {
    let newIndex = activeIndex + 1;
    if (newIndex >= devices.length) {
        newIndex = 0;
    }
    changeCamera(newIndex);
}, false);

function decode() {
    if (localStream) {
        var canvas = document.getElementById('canvas');
        var ctx = canvas.getContext('2d');
        var img = document.getElementById('img');
        var h;
        var w;

        w = video.offsetWidth;
        h = video.offsetHeight;

        canvas.setAttribute('width', w);
        canvas.setAttribute('height', h);
        ctx.drawImage(video, 0, 0, w, h);

        decodeImageFromBase64(canvas.toDataURL('image/png'), function (decodeInformation) {
            var input = document.getElementById('qr');
            if (!(decodeInformation instanceof Error)) {
                input.value = decodeInformation;
            }
        });
    }
}

function startReadQR() {
    setInterval('decode()', 500);
}

function changeCamera(index) {
    if (localStream) {
        localStream.getVideoTracks()[0].stop();
    }

    activeIndex = index;
    iosRear = !iosRear;
    var p = document.getElementById('active-camera');
    p.innerHTML = devices[activeIndex].name + '(' + devices[activeIndex].id + ')';
    setCamera();
}

function setCamera() {
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || windiow.navigator.mozGetUserMedia;
    window.URL = window.URL || window.webkitURL;

    var videoOptions;

    if (ios) {
        videoOptions = {
            facingMode: {
                exact: (iosRear) ? 'environment' : 'user'
            },
            mandatory: {
                sourceId: devices[activeIndex].id,
                minWidth: 600,
                maxWidth: 800,
                minAspectRatio: 1.6
            },
            optional: []
        };
    } else {
        videoOptions = {
            mandatory: {
                sourceId: devices[activeIndex].id,
                minWidth: 600,
                maxWidth: 800,
                minAspectRatio: 1.6
            },
            optional: []
        };
    }

    navigator.getUserMedia(
        {
            audio: false,
            video: videoOptions
        },
        function (stream) {
            if (ios) {
                video.srcObject = stream;
            } else {
                video.src = window.URL.createObjectURL(stream);
            }
            localStream = stream;
        },
        function (err) {

        }
    );

    startReadQR();
}
</script>

</html>

WebサイトからカメラでQRコードを読み取る – Android、iOS、PC対応 (ちょっとだけ改良版)」への2件のフィードバック

  1. 山内万寿夫

    gimp2をインストールしたのですが、フォト・プリントという無料の写真印刷用アプリケーション
    ソフトができませんでした。よろしくお願いいたします。
                 私事でありますが、北九州商工会議所 PC教室で学習しました。
                  よろしくお願いいたします。

    返信
  2. 山内万寿夫

    私事ですが、このページあります。文字、数式の事に関しては全くわかりません。
    PC 75才から始めて今に至ります。

    返信

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)