はじめに
物品管理や来店受付、在庫管理など、バーコードやQRコードを読み取る場面は意外と多いものです。今回はプリザンターの分類項目にカメラでバーコードやQRコードを読み取って入力する機能を、拡張機能だけで実現してみます。
ユーザ項目の「自分」ボタンや日付項目の「今」ボタンのように、分類項目の横にスキャンアイコンを配置して、クリックするとカメラのプレビューウインドウが起動し、読み取った値が分類項目に入力されるイメージです。
全体の流れ
使用するライブラリ
html5-qrcode を使用します。ブラウザのカメラAPIを利用してバーコードとQRコードの両方を読み取ることができるライブラリです。CDNから読み込むことで、プリザンター本体にファイルを配置する必要はありません。
対応フォーマットは QRコード、Code 128、Code 39、EAN-13、EAN-8、UPC-A など主要なものを網羅しています。
実装してみよう
今回の実装は3つの拡張機能を組み合わせます。
| 拡張機能 | 役割 |
|---|---|
| 拡張HTML | CDNからライブラリを読み込む |
| 拡張スクリプト | ボタンの追加・スキャン処理 |
| 拡張スタイル | モーダルやボタンの見た目を定義 |
ライブラリの読み込み(拡張HTML)
まずは html5-qrcode を CDN から読み込みます。拡張HTMLの HtmlHeaderBottom.html に記載します。
<script src="https://cdn.jsdelivr.net/npm/html5-qrcode@2.3.8/html5-qrcode.min.js"></script>
CDNを使用したライブラリの読み込み方法の詳細については「プリザンターでjsDelivrなどのライブラリCDNを使う方法」で紹介しています。
おまけ:CDNが使えない環境での読み込み方法
イントラネット環境などCDNにアクセスできない場合は、ライブラリファイルを直接配置する方法もあります。
GitHubのリリースページまたは npm から html5-qrcode.min.js を取得して、プリザンターの wwwroot 配下に配置します。
wwwroot/
scripts/
html5-qrcode.min.js
拡張HTMLの記述をローカルパスに変更します。
<script src="/scripts/html5-qrcode.min.js"></script>
スクリプト・スタイル部分は同じものをそのまま使用できます。
モーダルとボタンのスタイル(拡張スタイル)
スキャンボタンやモーダルウインドウの見た目を定義します。拡張スタイルとして App_Data/Parameters/ExtendedStyles/ に配置します。
/* date-field と同じレイアウト:入力欄の右端にボタンを配置 */
.barcode-field {
position: relative;
display: block;
}
.barcode-field .control-textbox {
padding-right: 24px;
}
.barcode-scan-trigger {
position: absolute;
top: 0;
right: 0;
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 100%;
margin: 0;
padding: 0;
background: transparent;
border: none;
outline: none;
cursor: pointer;
}
.barcode-scan-trigger .material-symbols-sharp {
font-size: 16px;
}
#barcode-modal .barcode-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 9998;
}
#barcode-modal .barcode-dialog {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #fff;
border-radius: 8px;
padding: 16px;
z-index: 9999;
min-width: 350px;
max-width: 90vw;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}
/* 横長画面:高さ50%を基準にサイズ確保 */
@media (orientation: landscape) {
#barcode-modal .barcode-dialog {
width: min(60vw, 640px);
height: 50vh;
}
#barcode-modal #barcode-reader {
height: calc(50vh - 72px);
}
}
/* 縦長画面:横幅いっぱいに収める */
@media (orientation: portrait) {
#barcode-modal .barcode-dialog {
width: 90vw;
max-height: 70vh;
}
#barcode-modal #barcode-reader {
height: calc(70vh - 72px);
max-height: 50vw;
}
}
#barcode-modal .barcode-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
font-weight: bold;
}
#barcode-modal #barcode-error {
margin-top: 8px;
color: red;
font-size: 12px;
}
/* html5-qrcode が生成する要素の余白を除去 */
#barcode-reader {
overflow: hidden;
border: none !important;
}
#barcode-reader video {
width: 100% !important;
height: 100% !important;
object-fit: cover;
display: block;
}
#barcode-reader img[alt="end"],
#barcode-reader img[alt="Info"] {
display: none;
}
スキャンボタンの追加と読み取り処理(拡張スクリプト)
分類項目にスキャンボタンを追加し、バーコード/QRコードの読み取り処理を実装します。拡張スクリプトとして App_Data/Parameters/ExtendedScripts/ に配置します。
$(function () {
// barcode クラスが付与された分類項目にスキャンボタンを追加
$('.control-textbox.barcode').each(function () {
var $input = $(this);
// date-field と同じ構造:ラッパーで囲んで右端にボタンを配置
$input.wrap('<div class="barcode-field"></div>');
var $btn = $('<button>', {
type: 'button',
class: 'barcode-scan-trigger',
title: 'バーコード/QRコードを読み取る'
}).append(
$('<span>', { class: 'material-symbols-sharp is-fill', text: 'qr_code_scanner' })
).on('click', function (e) {
e.preventDefault();
startScan($input.attr('id'));
});
$input.after($btn);
});
});
var scanner = null;
var currentTargetId = null;
// スキャン開始
function startScan(controlId) {
currentTargetId = controlId;
// モーダルが未生成なら作成
if (!$('#barcode-modal').length) {
$('body').append(
'<div id="barcode-modal">' +
'<div class="barcode-overlay"></div>' +
'<div class="barcode-dialog">' +
'<div class="barcode-header">' +
'<span>バーコード/QRコード スキャン</span>' +
'<button type="button" id="barcode-close" class="barcode-scan-trigger" style="position:static;width:auto;height:auto;">' +
'<span class="material-symbols-sharp is-fill">close</span>' +
'</button>' +
'</div>' +
'<div id="barcode-reader"></div>' +
'<p id="barcode-error"></p>' +
'</div>' +
'</div>'
);
$('#barcode-close, .barcode-overlay').on('click', stopScan);
}
$('#barcode-error').text('');
$('#barcode-modal').show();
// カメラを起動してスキャン開始
scanner = new Html5Qrcode('barcode-reader');
scanner.start(
{ facingMode: 'environment' },
{ fps: 10, qrbox: { width: 250, height: 250 } },
function (decodedText) {
// 読み取り成功 → 分類項目に値をセットしてモーダルを閉じる
$p.set($('#' + currentTargetId), decodedText);
stopScan();
},
function () {
// 読み取り中(検出できなかったフレームは無視)
}
).catch(function () {
$('#barcode-error').text('カメラの起動に失敗しました');
});
}
// スキャン停止
function stopScan() {
if (scanner) {
scanner.stop().then(function () {
scanner.clear();
}).catch(function () {});
scanner = null;
}
$('#barcode-modal').hide();
currentTargetId = null;
}
ポイントを見ていきましょう。
- スタイルは拡張スタイル
BarcodeReader.cssに分離しているため、CSSの管理・修正が容易です -
$('.control-textbox.barcode')でコントロールCSSにbarcodeが設定された分類項目を検索しています -
$input.wrap()で入力欄を.barcode-fieldラッパーで囲み、日付項目のdate-fieldと同じ構造を作っています - ボタンにはプリザンター内部で読み込み済みの Google Material Symbols を使用し、
qr_code_scannerアイコンを表示しています。日付項目の「今」ボタン(scheduleアイコン)と同じスタイル設定(font-family: 'Material Symbols Sharp'、font-variation-settings: 'FILL' 1)で統一感があります -
Html5Qrcodeでカメラを起動し、背面カメラ(environment)を優先的に使用します。PCの場合は利用可能なカメラが自動選択されます - バーコードまたはQRコードを検出すると
$p.setで分類項目に値をセットしてモーダルを閉じます
サイト設定
バーコードリーダーを使用したい分類項目の「コントロールCSS」に barcode を設定します。
テーブルの管理 → エディタ → 対象の分類項目 → 詳細設定 → コントロールCSS に barcode と入力してください。
選択肢一覧は使用せず、テキスト入力の分類項目として使用してください。ドロップダウンやラジオボタンの場合はスキャンした値を直接入力できないため、選択肢一覧を空にしておく必要があります。
カメラへのアクセスにはHTTPS接続が必要です。HTTP環境ではカメラが起動しない場合があります(localhost は例外)。
実行してみる
では、実際に実行してみましょう。前章のサイト設定を参考に分類項目(ノーマルとワイド)に設定してみました。
分類項目の右側に出ているQRコードアイコンをクリックするとプレビュー画面が立ち上がり読取りが出来ます。
まとめ
今回はプリザンターの分類項目にバーコードリーダー機能を追加する方法を紹介しました。
- 拡張HTML・拡張スクリプトのみで実装でき、本体の改修は不要
-
html5-qrcodeライブラリをCDNから読み込むことでバーコードとQRコードの両方に対応 - コントロールCSSで対象の分類項目を指定するため、必要な項目だけに機能を追加可能
- 日付項目の「今」ボタンと同じ
date-fieldパターン(Material Symbols アイコン+入力欄右端配置)で統一感のあるUI
物品管理や来店受付、在庫管理など様々な場面で活用できます。是非試してみてください。

