※初心者のため、間違いや何かご存じの方がいましたら、教えていただけると助かります。
作ったもの
概要
今回のアプリで、typescriptで使えるバーコードリーダーライブラリとして、Quagga.jsとZXingが候補に挙がった。
どちらを使うか。
環境
windows11
docker-desktop
Next.js(app routerを使用)
supabase
ホスティング:Vercel
内容
以下は、BingAIにまとめてもらった表。
特徴 | Quagga.js | ZXing |
---|---|---|
言語 | JavaScript | Java, JavaScript, C++, C#, Objective-C, Python, Rust, etc. |
対応バーコード | EAN, Code 128, Code 39, Interleaved 2 of 5, UPC, etc. | QR Code, Data Matrix, Aztec, PDF 417, EAN, UPC, Code 128, etc. |
ブラウザ対応 | はい | はい |
モバイル対応 | はい | はい |
ライセンス | MIT License | Apache License 2.0 |
ドキュメント | 比較的少ない | 豊富 |
パフォーマンス | 高速だが、特定のバーコードに最適化されている | 幅広いバーコードに対応しており、全体的に高性能 |
コミュニティ | 活発だが、ZXingほど大きくはない | 非常に活発で広範囲 |
使用例 | ウェブアプリケーションでのバーコードスキャン | モバイルアプリケーション、デスクトップアプリケーション、ウェブアプリケーション |
Quaggaは高速だが、1Dコードしか対応していない。
ZXingは少し遅い?が、2Dコード(QRコード)にも対応。
各コード例(components/BarcodeScanner.tsx)
Quagga.js(今回、Quaggaは、以下のコードではうまく動かなかった。ビデオは起動するが、読み取ってくれない。原因までわからず。)
import Quagga from "quagga";
import { useEffect, useRef, useState } from "react";
interface BarcodeScannerProps {
onScan: (code: string) => void;
}
const BarcodeScanner: React.FC<BarcodeScannerProps> = ({ onScan }) => {
const [scanning, setScanning] = useState(false);
const videoRef = useRef<HTMLVideoElement>(null);
useEffect(() => {
if (scanning) {
Quagga.init(
{
inputStream: {
type: "LiveStream",
target: videoRef.current,
constraints: {
facingMode: "environment",
},
},
decoder: {
readers: [
"code_128_reader",
"ean_reader",
"ean_8_reader",
"code_39_reader",
"code_39_vin_reader",
"codabar_reader",
"upc_reader",
"upc_e_reader",
"i2of5_reader",
],
},
},
(error: any) => {
if (error) {
console.log(error);
setScanning(false);
return;
}
Quagga.start();
}
);
}
return () => {
if (scanning) {
Quagga.stop();
}
};
}, [scanning, onScan]);
return (
<div>
<button
style={{ //css調整
width: "50%",
margin: "0 auto",
display: "block",
border: "1px solid black",
}}
onClick={() => setScanning(true)}
>
バーコードスキャン
</button>
{scanning && (
<div
ref={videoRef}
style={{ width: "80%", height: "50%", margin: "0 auto" }} //css調整
/>
)}
</div>
);
};
export default BarcodeScanner;
ZXing
import { BrowserMultiFormatReader } from "@zxing/library";
import { useEffect, useRef, useState } from "react";
const BarcodeScanner = ({ onScan }: { onScan: (code: string) => void }) => {
const [scanning, setScanning] = useState(false);
const videoRef = useRef<HTMLVideoElement>(null);
useEffect(() => {
if (scanning) {
const codeReader = new BrowserMultiFormatReader();
codeReader.decodeFromVideoDevice(
null,
videoRef.current,
(result, err) => {
if (result) {
onScan(result.getText());
setScanning(false);
codeReader.reset();
}
}
);
}
}, [scanning, onScan]);
return (
<div>
{!scanning ? (
<button
style={{ //css調整
width: "50%",
height: "100px",
margin: "0 auto",
display: "block",
border: "1px solid black",
backgroundColor: "white",
font: "bold 18px sans-serif",
}}
onClick={() => setScanning(true)}
>
バーコードで検索<br></br>(カメラを起動)
</button>
) : (
"カメラ起動"
)}
{scanning && (
<video
ref={videoRef}
style={{ //css調整
width: "90%",
height: "60%",
margin: "0 auto",
}}
/>
)}
</div>
);
};
export default BarcodeScanner;
まとめ
最終的に、「商品の同一性」判定が目的であり、将来的にバーコードが2DのQRコードに変わっていく可能性も考え、ZXingを利用することにした。
ここで読み取ったコードをもとに、yahoo shoppingAPIを叩いて該当商品があれば商品名を取得する。もし、登録済み商品のデータがあれば、その情報を表示する仕様にした。
次回は、本アプリで検索機能を何度か実装したので、それに関する備忘録を残す予定。