Skip to main content

barcode recognition in React

REF

React上でブックカバーのバーコードから商品の画像を取得するライブラリを公開しました。 Webでカメラからバーコードを認識して探索結果の一覧を表示します。 デモで用いたコードは、Githubで公開してます。

スキャナーのサンプルコード

開始時に実行する関数onStartedと認識後に実行する関数onDetectedは、親コンポーネントからpropsとして入力します。 (再Renderするといくつも開始してしまうので、これらの関数はuseRef内で再定義させます.) useEffect内の①にはQuaggaの初期化処理、②にはQuaggaがバーコードを認識した際の処理を後で入れます。 また、Canvasに認識結果を描写する関数のdrawPath(), drawRect(), clearRect()を定義しておきます。

import React, { useCallback, useEffect, useRef } from "react";
import config from "./config-camera.json";
const Quagga = require ('quagga');

export function Scanner ({onStarted, onDetected}) {
const onStartedRef = useRef((bool)=>onStarted(bool))
const onDetectedRef = useRef((code)=>onDetected(code))
const drawPath = useCallback((path,ctx,xy,color) => Quagga.ImageDebug.drawPath(path,xy,ctx,{color,lineWidth:2}),[])
const drawRect = useCallback((path,ctx,isMain) => drawPath(path,ctx,{x:0,y:1},isMain?'#0F0':"#00F"),[])
const clearRect = useCallback((dom,ctx) => ctx.clearRect(0,0,...["width","height"].map(s=>Number(dom.getAttribute(s)))),[])

useEffect ( () => {/*...①...*/}, [] ) // 後述
useEffect( () => {/*...②...*/}, [] ) // 後述

return <div id="interactive" className="viewport" style={{width:"100%",height:"100%"}}/>
}

Quaggaの初期化と認識処理

カメラの起動はQuagga.init()を実行してから数秒間かかります。 起動したかをonStarted()で親コンポーネントに伝え、カメラが開始してから表示させます。

  useEffect (() => {/*...①...*/
Quagga.init(config, (err) => {
if (err) return
return (Quagga.start(), onStartedRef.current(true))
})
return ()=>(Quagga.stop(), onStartedRef.current(false))
}, []);

result.boxesresult.boxにはバーコードを検出した情報があるので、場合によって色を変えます。

  useEffect(()=>{/*...②...*/
Quagga.onProcessed( (result) => {
if (!result) return
const ctx = Quagga.canvas.ctx.overlay
const dom = Quagga.canvas.dom.overlay
result.boxes && clearRect(dom, ctx)
result.boxes.forEach( box => drawRect(box,ctx,box===result.box) )
result.codeResult && drawPath(result.line,ctx,{x:"x",y:"y"},"#F00")
});
Quagga.onDetected((result) => onDetectedRef.current(result.codeResult.code))
}, [])

以上で、開始したときと認識したときに実行するonStarted, onDetected関数を定義すれば、 <Scanner {{...onStarted, onDetected}}/>のように使用できます。

また、Quaggajsはcanvasを作成するので、次の様なCSSを別で用意しておく必要があります。

#interactive.viewport canvas.drawingBuffer,
#interactive.viewport canvas, video {
width:100%; height:auto;
position:absolute; top:0; left:0;
border-radius:2em 2em 0px;
}