633 views
この記事は最終更新から 955日 が経過しています。
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);
});
}
});
アクセス数(直近7日): ※試験運用中、BOT除外簡易実装済2026-07-28: 2回 2026-07-27: 0回 2026-07-26: 0回 2026-07-25: 0回 2026-07-24: 0回 2026-07-23: 0回 2026-07-22: 0回