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.boxes
、result.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;
}