112 views
1. やりたいこと
前回の投稿 (142) JavaScriptでISBN書籍情報を取得・表示する。 では、テキストボックス内に入力した ISBNコードを使って Google Books API に問合せ、取得した書籍情報を画面上に表示する JavaScriptプログラムを作った。
今回はこれを更に改造し、
Webブラウザ上の操作でスマホのカメラを起動し、
→ カメラ映像中の ISBNコードを自動で判読し、
→ その値をテキストボックスに入力する
という処理を追加したい。
これが実装できると、
Webブラウザ上でスマホカメラを使って ISBNコードを読み取り、
Google Books APIで取得した書籍情報をWebブラウザ上に表示する
までを一気通貫で出来るようになる。
2. やってみる
動作確認した環境は以下の通り。
・Android: Chrome
・iPhone, iPad: Chrome, Safari
※Webブラウザの設定で、カメラへのアクセスを拒否している場合、設定変更が必要!
実装済みのページはこちら。
https://www.dogrow.net/hp/sample/00143/
1) 使用するバーコードリーダーライブラリ
今回は Quagga バーコードリーダーを利用させていただく。
公式サイト: https://serratus.github.io/quaggaJS/
GitHub: https://github.com/serratus/quaggaJS
今回は、GitHubからダウンロードしたソースの中から quagga.min.js を使わせていただく。
2) 画面仕様
3) 実装&動作確認したプログラムソースコード
(1) index.html
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Blog #143</title> <link rel="stylesheet" href="style.css" /> <script src="quagga.min.js"></script> <script src="script.js"></script> </head> <body> <input id="btnStartCamera" class="btn" type="button" value="カメラ起動" /> <input id="btnStartScan" class="btn" type="button" value="ISBNスキャン" disabled="true" /> <p id="ISBNShow"></p> <div id="CameraView"><div id="ScanFrame"></div></div> <div id="BookInfo"></div> </body> </html>
(2) style.css
*{ /* 全体 */ margin: 0; box-sizing: border-box; } .btn{ /* ボタン */ font-size: 2rem; width: 100%; } #ScanFrame{ /* スキャン領域の枠線 */ position: absolute; display: none; top: 30%; left: 10%; height: 20%; width: 80%; border: 5px #ff0 solid; z-index: 1; } #CameraView{ /* カメラ映像表示欄 */ position: relative; display: none; top: 0; left: 0; width: 100%; height: 100%; } #ISBNShow{ /* ISBNコード表示欄 */ margin: 1rem; font-size: 1.5rem; text-align: center; } #BookInfo{ /* 書籍情報表示欄 */ border:2px solid #F00; } /* 以下の要素は、Quaggaが自動的に埋め込んでいる。 これらの要素の表示幅が画面幅をオーバーしている。→ 表示幅を制限したい。 */ canvas, video { width: 100% !important; height: auto !important; } canvas{ position: absolute; }
(3) script.js
プログラムソースコード中にコメントを記述したので、ここでの解説は省略する。
// DOM生成完了通知イベントハンドラを登録する。 document.addEventListener("DOMContentLoaded", function() { const divCameraView = document.getElementById('CameraView'); const divScanFrame = document.getElementById('ScanFrame'); const divBookInfo = document.getElementById('BookInfo'); const divshowISBN = document.getElementById('ISBNShow'); const btnStartCamera = document.getElementById('btnStartCamera'); const btnStartScan = document.getElementById('btnStartScan'); ////////////////////////////////////////////////////////////////////////////// // [カメラ起動]ボタン押下時のイベントハンドラを登録する。 btnStartCamera.addEventListener('click', function() { this.disabled = true; // [カメラ起動]ボタンを無効化 btnStartScan.disabled = false; // [ISBNスキャン]ボタンを有効化 divCameraView.style.display = 'block'; // カメラ映像表示欄 表示ON divScanFrame.style.display = 'block'; // スキャン枠 表示ON divBookInfo.innerText = ''; // 書籍情報欄をクリア divshowISBN.innerText = ''; // ISBNコード表示欄をクリア activateCamera(); // カメラ起動 }); ////////////////////////////////////////////////////////////////////////////// // [ISBNスキャン]ボタン押下時のイベントハンドラを登録する。 btnStartScan.addEventListener('click', function() { this.disabled = true; // [ISBNスキャン]ボタンを無効化 startScanning(); // スキャン開始 }); ////////////////////////////////////////////////////////////////////////////// // 関数:カメラ起動 function activateCamera() { // init( {成功時の関数}, {失敗時の関数} ) Quagga.init({ // Quagga初期化 inputStream: { name: 'MyScanProc', type: 'LiveStream', target: divCameraView, // カメラ映像の表示領域を指定 constraints: { facingMode: 'environment', // スマホの背面カメラを使用 width: { min: 640, ideal: 1280, max: 1920 }, // スキャン時の画像解像度(H方向)を指定 height: { min: 480, ideal: 720, max: 1080 } // スキャン時の画像解像度(V方向)を指定 }, area: { // スキャン領域を指定 ※親要素の矩形範囲を基準に指定する。 top: '30%', // 画面上部からの距離 right: '10%', // 画面右端からの距離 left: '10%', // 画面左端からの距離 bottom: '50%' // 画面下部からの距離 } }, decoder: { readers: ['ean_reader'] // 読み取り対象のバーコードは EAN (EAN-13等)を指定 }, locate: false // バーコードの自動検出を無効化 // ※上でarea指定しているので自動検出は無効でよい。 }, function(err) { // init()の第2引数 (=失敗時の関数) if(err){ console.log(err); return; } }); // バーコード検出完了時のイベントハンドラを登録する。 Quagga.onDetected(onDetectedCallback); } ////////////////////////////////////////////////////////////////////////////// // 関数:バーコードのスキャン完了通知イベントハンドラ function onDetectedCallback(result) { Quagga.stop(); // スキャンを停止する。 Quagga.offDetected(onDetectedCallback); // バーコード検出完了時のイベントハンドラを削除する。 var isbn = result.codeResult.code; // 読み出したISBNコードを取得する。 divshowISBN.innerText = isbn; // ISBNコードの表示欄に表示する。 btnStartCamera.disabled = false; // [カメラ起動]ボタンを有効化 divScanFrame.style.display = 'none'; // スキャン枠 表示OFF divCameraView.style.display = 'none'; // カメラ映像表示欄 表示OFF startISBNQuery(); // Google Books APIにISBN問合せを実行する。 } ////////////////////////////////////////////////////////////////////////////// // 関数:バーコードのスキャンを開始 function startScanning() { Quagga.start(); } ////////////////////////////////////////////////////////////////////////////// // 関数:Google Books APIにISBN問合せ function startISBNQuery(){ var isbn = divshowISBN.innerText; // ISBNコード表示欄から値を取得する。 // Google Books Web APIを使って指定したISBNに対応する書籍情報を取得する。 fetch(`https://www.googleapis.com/books/v1/volumes?q=isbn:${isbn}`) .then(resp => resp.json()) // 連結#1:受信データをデコードして JSONオブジェクトを生成 .then(data => { // 連結#2:JSONオブジェクトを受け取り console.log(data); // 書籍データの解析と表示 if(data.items && data.items.length > 0){ var book = data.items[0].volumeInfo; // 書籍情報を表示する。 divBookInfo.innerHTML = ` タイトル: ${book.title}<br /> 著者: ${book.authors}<br /> 出版社: ${book.publisher} `; }else{ divBookInfo.innerHTML = `${isbn}の書籍情報が見つかりませんでした。`; } }) .catch(error => { console.error('Error fetching data:', error); }); } });