Edited at

JavaScriptでQRコードをスキャンするライブラリまとめ

More than 1 year has passed since last update.

QRコードをブラウザで読み取ることができるJavaScriptのライブラリを調査しました。


調査したライブラリ

GitHub

:star: Star

:fork_and_knife: Fork

:arrow_down: downloads in the last month at npm
Demo

LazarSoft/jsqrcode
2359
776

9664 or 796

https://webqr.com/

schmich/instascan
643
192
1698
https://schmich.github.io/instascan/

cozmo/jsQR
128
30
3456
https://cozmo.github.io/jsQR/

JodusNodus/react-qr-reader
146
43
10205
https://thomasbilliet.com/react-qr-reader/


LazarSoft/jsqrcode

ZXing というJavaのライブラリをJavaScriptに移植したものです。

このライブラリ自体はCommonJS形式で書かれていないのですが,別の方がCommonJS形式への変換とnpmの登録をしてくれていて,edi9999/jsqrcodevicapow/jsqrcode という2種類のプロジェクトがあります。

このライブラリはテストコードが不十分ということで,edi9999/jsqrcode の作者は,後述する cozmo/jsQR の利用を推奨しています。

このライブラリは画像ファイルのDataURLからQRコードを読み込むところまでを対象としているので,Webカメラから画像を取得する処理は navigator.getUserMedia などを使って自分で書く必要があります。参考事例を2つ挙げておきます。


schmich/instascan

前述の LazarSoft/jsqrcode のもととなったライブラリである ZXing というJavaのライブラリをC++に移植した zxing-cpp をEmscriptenでJavaScriptに変換した zxing-cpp-emscripten のラッパーです(長い)。

このライブラリはWebカメラからの画像の取得までやってくれるようなのですが,READMEにはiOS Safariには対応していないという旨のことが書いてあります。これは,iOS Safariで navigator.getUserMedia が使えるようになったのが最近のこと(iOS11以降)だからです。 もしかすると現在のiOS Safariでは普通に使えるのかもしれません(手元にiOSが無いので検証できません)。 @syoyo さんの検証によるとiOS11でも動作しなかったようです。以下のPRが取り込まれていないのを見ても分かるように,最近は開発が停滞気味です。


cozmo/jsQR

最初からCommonJS形式で書かれていたり,テストコードがちゃんと書かれていたり,Typed Arrayが使われていたり,TypeScriptで記述されていたりと,モダンなライブラリとなっています。

使い方は画像データを ImageData 形式で準備してから jsQR(imageData, width, height) に渡すだけというシンプルなインターフェースになっていますが,これもjsqrcodeと同様にWebカメラから画像を取得する処理は自分で書く必要があります。


JodusNodus/react-qr-reader

前述の cozmo/jsQR をReactコンポーネントとしてラップしたものです。Webカメラからの画像取得までやってくれるeasyなライブラリで,npmのダウンロード数の観点では一番人気があります。

jsQRでQRコードをスキャンする処理はCPUで行われるので,シングルスレッドで駆動するJavaScriptにとって苦手な処理なのですが,このライブラリではjsQRでの処理をWeb Workerで別スレッドにオフロードすることでUIスレッドへの影響を小さくしています。


これらのライブラリはモバイルDapp用に使えるか?

Status などのモバイルDappブラウザ上でQRコードが使えたら非常に便利なのですが,試してみたところ動作しませんでした。Statusの場合はReact Native上のWebViewを使っているので一筋縄ではいかないようです。もしかすると react-native-webview-bridge あたりに手を加える必要があるのかもしれません。

追記

まさにこの問題を解決するPull Requestが上がっていました!

react-native-webview-bridgeのPull Request を取り込むことでカメラにアクセスできるようになりそうです。近日中に取り込まれるようになるのではないでしょうか?