tag:crieit.net,2005:https://crieit.net/tags/%E3%83%90%E3%83%BC%E3%82%B3%E3%83%BC%E3%83%89/feed
「バーコード」の記事 - Crieit
Crieitでタグ「バーコード」に投稿された最近の記事
2019-09-18T11:04:27+09:00
https://crieit.net/tags/%E3%83%90%E3%83%BC%E3%82%B3%E3%83%BC%E3%83%89/feed
tag:crieit.net,2005:PublicArticle/15406
2019-09-18T11:04:27+09:00
2019-09-18T11:04:27+09:00
https://crieit.net/posts/Nuxt-js-iOS-PWA
Nuxt.jsでバーコードリーダを作ったら、いろいろハマった上にiOSのPWAでカメラにアクセスできなかった話
<p>Nuxt.jsで開発している<a target="_blank" rel="nofollow noopener" href="https://tsundoku.site">Webサービス</a>にバーコードリーダ機能をつけようとしたら、<br />
いろいろハマったので、そのときの備忘録。</p>
<p>利用したのは<a target="_blank" rel="nofollow noopener" href="https://serratus.github.io/quaggaJS/">QuaggaJS</a>。簡単に使えて便利(<em>´ω`</em>)</p>
<p>はまったポイントは、以下の4点...<br />
1. httpsじゃないとカメラを取得できない<br />
2. QuaggaJSで表示されてないHTML要素を指定するとエラー<br />
3. size/width/heightを指定してもいい感じにならない<br />
4. iOSのPWAではカメラにアクセスできない</p>
<p>いろいろハマったけど、QuaggaJS自体がすごく良いので、サクッとできた♪</p>
<h3 id="作ったのはこんな感じ"><a href="#%E4%BD%9C%E3%81%A3%E3%81%9F%E3%81%AE%E3%81%AF%E3%81%93%E3%82%93%E3%81%AA%E6%84%9F%E3%81%98">作ったのはこんな感じ</a></h3>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">バーコードリーダ、できてきた♪いい感じな気がする(*´ω`*) <a target="_blank" rel="nofollow noopener" href="https://t.co/eDJH4P57pZ">pic.twitter.com/eDJH4P57pZ</a></p>— 積読ハウマッチ📚きらぷか (@kira_puka) <a target="_blank" rel="nofollow noopener" href="https://twitter.com/kira_puka/status/1173965092649521152?ref_src=twsrc%5Etfw">September 17, 2019</a></blockquote>
<p>動きとしては、こんな感じでシンプル。</p>
<ol>
<li>ボタンを押すと、モーダルが開いて、カメラ移動</li>
<li>バーコードを読み取り終えると、終了してPageに結果を返す</li>
</ol>
<p><img width="600" alt="スクリーンショット 2019-09-18 8.18.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/b3d4472e-8214-c260-b627-e3c7f603a7f5.png"></p>
<hr />
<h2 id="QuaggaJSを使ってみる"><a href="#QuaggaJS%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B">QuaggaJSを使ってみる</a></h2>
<p>使い方はこんな感じ。</p>
<h3 id="まずはインストール"><a href="#%E3%81%BE%E3%81%9A%E3%81%AF%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">まずはインストール</a></h3>
<pre><code class="console">$ npm i -S quagga
</code></pre>
<h3 id="バーコードリーダモーダルはこんな感じ"><a href="#%E3%83%90%E3%83%BC%E3%82%B3%E3%83%BC%E3%83%89%E3%83%AA%E3%83%BC%E3%83%80%E3%83%A2%E3%83%BC%E3%83%80%E3%83%AB%E3%81%AF%E3%81%93%E3%82%93%E3%81%AA%E6%84%9F%E3%81%98">バーコードリーダモーダルはこんな感じ</a></h3>
<p>CSSには<a target="_blank" rel="nofollow noopener" href="https://bulma.io">Bulma</a>を利用してます。</p>
<pre><code class="html"><template>
<div class="dialog modal is-active" v-if="active">
<div class="modal-background"></div>
<div class="modal-content">
<!-- カメラの映像を表示させるDIV -->
<div id="camera-area" class="camera-area"></div>
</div>
<!-- 右上の閉じるボタン -->
<button class="modal-close is-large" aria-label="close" @click.prevent.stop="onClickCancel"></button>
</div>
</template>
<script lang="ts">
import { Component, Vue, Prop, Emit, Watch } from "nuxt-property-decorator";
@Component
export default class ModalReader extends Vue {
// モーダルの表示/非表示のprop
@Prop({ required: true }) active!: boolean;
// QuaggaJSのインスタンス
private Quagga;
/**
* Vueインスタンス破棄時、カメラを起動していたらストップする
*/
destroyed() {
if (!!this.Quagga) this.Quagga.stop();
}
// ****************************************************
// * watch
// ****************************************************
/**
* this.activeを監視してQuaggaの開始/停止をする
*/
@Watch("active")
private onChangeActive(val: boolean) {
this.$nextTick(() => {
if (val) {
// モーダル表示時、Quaggaを起動
this.initQuagga();
} else {
// モーダル非表示時、Quaggaを停止
if (!!this.Quagga) this.Quagga.stop();
}
});
}
// ****************************************************
// * methods
// ****************************************************
/**
* Quaggaの初期化処理
*/
private initQuagga() {
// requireで読み込み
this.Quagga = require("quagga");
// バーコード検出時の処理を設定
this.Quagga.onDetected(this.onDetected);
// Quaggaの設定項目
const config = {
// カメラの映像の設定
inputStream: {
type: "LiveStream",
// カメラ映像を表示するHTML要素の設定
target: document.querySelector("#camera-area"),
// バックカメラの利用を設定. (フロントカメラは"user")
constraints: { facingMode: "environment" },
// 検出範囲の指定: 上下30%は対象外
area: { top: "30%", right: "0%", left: "0%", bottom: "30%" }
},
// 解析するワーカ数の設定
numOfWorkers: navigator.hardwareConcurrency || 4,
// バーコードの種類を設定: ISBNは"ean_reader"
decoder: { readers: ["ean_reader"] }
}
// 初期化の開始。合わせて、初期化後の処理を設定
this.Quagga.init(config, this.onInitilize);
}
/**
* Quaggaの初期化完了後の処理
* errorがなければ、起動する
*/
private onInitilize(error) {
if (!!error) {
// エラーがある場合は、キャンセルをEmitする
console.error(`Error: ${error}`, error);
this.onClickCancel();
return;
}
// エラーがない場合は、読み取りを開始
console.info("Initialization finished. Ready to start");
this.Quagga.start();
}
/**
* バーコード検出時の処理
*/
private onDetected(success) {
// ISBNは'success.codeResult.code'から取得
const isbn = success.codeResult.code;
// ISBNをEmitで返却する
this.onSuccess(isbn);
}
// ****************************************************
// * emit
// ****************************************************
@Emit("cancel")
private onClickCancel() {}
@Emit("success")
private onSuccess(code) {
return code;
}
}
</script>
<style lang="scss">
.camera-area {
overflow: hidden;
height: 300px;
width: 300px;
/**
* 指定したDIV配下にvideoとcanvasが追加される
* 4:3になるため、margin-topで調整
*/
video, canvas {
margin-top: -50px;
width: 300px;
height: 400px;
}
}
</style>
</code></pre>
<p>ページ側でpropのactiveを切り替えて、モーダルの表示をすればOK。簡単(<em>´ω`</em>)</p>
<p>videoやcanvasなどは、Quaggaが生成するよう。</p>
<p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/fdf8635d-b5aa-70cd-c56c-5c1970e703b2.png" alt="スクリーンショット 2019-09-18 10.03.48.png" /></p>
<hr />
<h2 id="はまったポイント..."><a href="#%E3%81%AF%E3%81%BE%E3%81%A3%E3%81%9F%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88...">はまったポイント...</a></h2>
<p>PC上で開発しているときは割とサクッとできたんですが、<br />
テストでいろんなところにハマリポイントが..</p>
<h3 id="1. httpsじゃないとカメラを取得できない"><a href="#1.+https%E3%81%98%E3%82%83%E3%81%AA%E3%81%84%E3%81%A8%E3%82%AB%E3%83%A1%E3%83%A9%E3%82%92%E5%8F%96%E5%BE%97%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84">1. httpsじゃないとカメラを取得できない</a></h3>
<p>ローカルで実装できたので、nuxt.config.tsを以下のようにして、</p>
<pre><code class="typescript">const config: NuxtConfiguration = {
server: {
port: 3000,
host: "0.0.0.0"
}
};
</code></pre>
<p>Androidスマホから試してみたら、こんなエラーが...</p>
<blockquote>
<p>Error: getUserMedia is not defined</p>
</blockquote>
<p>以下の記事を見ると、Chromeではlocalhostかhttpsじゃないと動かないらしい...<br />
参考: <a target="_blank" rel="nofollow noopener" href="https://blog.ko31.com/201606/perari-to-https/">ChromeではgetUserMediaがHTTPS経由でないと動かなくなっていた – 打つか投げるか</a></p>
<p>以下のようなローカルで起動したNuxt.jsをhttps化する方法もあるけど、<br />
ステージング環境のFirebaseプロジェクトを用意して対応。。<br />
参考: <a target="_blank" rel="nofollow noopener" href="https://qiita.com/yoshinbo/items/5838f43cbbd75e396c35">Nuxt.jsでlocalhostをSSL化する方法 - Qiita</a></p>
<h3 id="2. QuaggaJSで表示されてないHTML要素を指定するとエラー"><a href="#2.+QuaggaJS%E3%81%A7%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%A6%E3%81%AA%E3%81%84HTML%E8%A6%81%E7%B4%A0%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B%E3%81%A8%E3%82%A8%E3%83%A9%E3%83%BC">2. QuaggaJSで表示されてないHTML要素を指定するとエラー</a></h3>
<p>初期化処理の以下の部分で<code>#camera-area</code>を指定してるが、<br />
最初はmounted内で行っていた。</p>
<pre><code class="javascript">private initQuagga() {
// Quaggaの設定項目
const config = {
// カメラの映像の設定
inputStream: {
// カメラ映像を表示するHTML要素の設定
target: document.querySelector("#camera-area"),
},
}
}
</code></pre>
<p>すると、こんなエラーが...</p>
<blockquote>
<p>error TypeError: Cannot read property 'setAttribute' of undefined<br />
at Object.o.createLiveStream</p>
</blockquote>
<p>よく見直してみると、<code>v-if="active"</code>で表示を切り替えているので、<br />
<code>document.querySelector("#camera-area")</code>で取得できてなかった...</p>
<h3 id="3. size/width/heightを指定してもいい感じにならない"><a href="#3.+size%2Fwidth%2Fheight%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%A6%E3%82%82%E3%81%84%E3%81%84%E6%84%9F%E3%81%98%E3%81%AB%E3%81%AA%E3%82%89%E3%81%AA%E3%81%84">3. size/width/heightを指定してもいい感じにならない</a></h3>
<p>公式サイトの<a target="_blank" rel="nofollow noopener" href="https://serratus.github.io/quaggaJS/">Example</a>に以下のサンプルがあったので試してみたところ、<br />
あまりいい感じではなかった...</p>
<pre><code class="javascript">inputStream: {
size: 800 // restrict input-size to be 800px in width (long-side)
}
</code></pre>
<p><code>#camera-area</code>のwidthを300にしていたため、<br />
<code>size: 300</code>で指定してみたところ、なかなか検出されず。。。<br />
この設定を外すとすぐに検出できた( ゚д゚)!</p>
<p>GitHubにあるexampleの<a target="_blank" rel="nofollow noopener" href="https://github.com/serratus/quaggaJS/blob/master/example/live_w_locator.html">quaggaJS/live_w_locator.html</a>を見てみると、<br />
<a target="_blank" rel="nofollow noopener" href="https://github.com/serratus/quaggaJS/blob/master/example/css/styles.css">CSS</a>で画面サイズとかを設定しているようなので、そちらを参考にした。</p>
<p>以下のように、constraintsでwidthとheightを指定できそうだったが、<br />
<a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/MediaDevices/getUserMedia">MediaDevices.getUserMedia()</a>で利用する<a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints">MediaStreamConstraints</a>の解像度の制約のよう...</p>
<pre><code class="javascript">inputStream: {
constraints: {
width: 640,
height: 480,
}
}
</code></pre>
<p>日本語の情報が少ないので、トライ&エラーで確認...</p>
<h3 id="4. iOSのPWAではカメラにアクセスできない"><a href="#4.+iOS%E3%81%AEPWA%E3%81%A7%E3%81%AF%E3%82%AB%E3%83%A1%E3%83%A9%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84">4. iOSのPWAではカメラにアクセスできない</a></h3>
<p>Androidもうまくいき、iOSのブラウザでもできるようになったが、<br />
iOSのPWAで確認したところ、またこのエラーが...</p>
<blockquote>
<p>Error: getUserMedia is not defined</p>
</blockquote>
<p>以下の記事を見てみると、iOSのPWAでは制限があるらしい...</p>
<blockquote>
<p>iOSのPWAでは表示モードがstandaloneの場合にカメラを開くことができない。</p>
</blockquote>
<p>参考: <a target="_blank" rel="nofollow noopener" href="https://qiita.com/1pp0/items/a3f0ea14910e25f49878">PWAでカメラを使うためiOSとAndroidで異なるmanifestを読み込む - Qiita</a></p>
<p>なんてこった。。ほんとうに残念である。。</p>
<p>仕方がないので<a target="_blank" rel="nofollow noopener" href="https://qiita.com/1pp0/items/a3f0ea14910e25f49878">参考記事</a>にあるように、<br />
Nuxt.jsでもmanifest.jsonを2つ用意してUAで切り替えるように変更。。</p>
<h4 id="【暫定対処】Nuxt.jsでOSに応じてmanifest.jsonを切り替える"><a href="#%E3%80%90%E6%9A%AB%E5%AE%9A%E5%AF%BE%E5%87%A6%E3%80%91Nuxt.js%E3%81%A7OS%E3%81%AB%E5%BF%9C%E3%81%98%E3%81%A6manifest.json%E3%82%92%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88%E3%82%8B">【暫定対処】Nuxt.jsでOSに応じてmanifest.jsonを切り替える</a></h4>
<p>方法としてはこんな感じ。</p>
<ol>
<li>iOS用のmanifest.json(manifest_ios.json)を用意する</li>
<li>UA応じたmanifest.jsonの<code><link></code>を生成するpluginを作成</li>
<li>作ったプラグインをnuxt.config.tsに設定</li>
</ol>
<h5 id="1. iOS用のmanifest.jsonの作成"><a href="#1.+iOS%E7%94%A8%E3%81%AEmanifest.json%E3%81%AE%E4%BD%9C%E6%88%90">1. iOS用のmanifest.jsonの作成</a></h5>
<p>参考記事にある通り、manifest.jsonをコピーして、<br />
<code>"display": "standalone"</code>を<code>"display": "browser"</code>にしただけの<br />
manifest_ios.jsonを作成する。</p>
<pre><code class="diff">--- static/manifest.json 2019-09-17 21:29:18.000000000 +0900
+++ static/manifest_ios.json 2019-09-18 00:21:54.000000000 +0900
@@ -3,7 +3,7 @@
"short_name": "積読ハウマッチ",
"description": "買った本を読まずに積んでおく「積読」、全部でいくらか知っていますか?「積読ハウマッチ」は積んである本の総額がわかる書籍管理サービスです。",
"start_url": "/",
- "display": "standalone",
+ "display": "browser",
"background_color": "#ffffff",
"theme_color": "#776f59",
"orientation": "portrait-primary",
</code></pre>
<h5>2. UA応じた<code><link></code>を生成するpluginを作成</h5>
<p>以下の<code>plugins/pwa-setup.ts</code>を作成。</p>
<pre><code class="typescript">const userAgent = navigator.userAgent.toLowerCase();
const iOS = userAgent.indexOf("iphone") > 0 || userAgent.indexOf("ipad") > 0;
// manifestのlinkタグを生成
function setManifest(path) {
const manifest = document.createElement("link");
manifest.rel = "manifest";
manifest.href = path;
document.head.appendChild(manifest);
}
setManifest(iOS ? "/manifest_ios.json" : "/manifest.json");
</code></pre>
<h5 id="3. nuxt.config.tsの設定"><a href="#3.+nuxt.config.ts%E3%81%AE%E8%A8%AD%E5%AE%9A">3. nuxt.config.tsの設定</a></h5>
<p>作ったプラグインをnuxt.config.tsに設定。</p>
<pre><code class="typescript">const config: NuxtConfiguration = {
plugins: [
{ src: "~/plugins/pwa-setup", ssr: false }
]
}
</code></pre>
<p>これでNuxt.jsでもUAに応じて切り替えができるように(<em>´ω`</em>)<br />
ただ、iOSのPWAがただのブラウザショートカットに...</p>
<hr />
<h2 id="おまけ: その他、もろもろ"><a href="#%E3%81%8A%E3%81%BE%E3%81%91%3A+%E3%81%9D%E3%81%AE%E4%BB%96%E3%80%81%E3%82%82%E3%82%8D%E3%82%82%E3%82%8D">おまけ: その他、もろもろ</a></h2>
<p>上記以外のQuaggaJSの使い方や開発で役立ったことを五月雨に。</p>
<h4 id="A) Android実機のデバッグはDevToolsでできる"><a href="#A%29+Android%E5%AE%9F%E6%A9%9F%E3%81%AE%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%81%AFDevTools%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B">A) Android実機のデバッグはDevToolsでできる</a></h4>
<p>Android実機でChromeを開いて確認していた時、コンソールログがみたいなと思ったら、<br />
DevToolsでリモートデバッグできた!! DevTollsすごい(<em>´ω`</em>)</p>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://developers.google.com/web/tools/chrome-devtools/remote-debugging/?hl=ja">Android 端末のリモート デバッグを行う | Tools for Web Developers | Google Developers</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/hojishi/items/12b726f8b02ef3d713e4">Android の Chrome で開発者ツールを使う方法 - Qiita</a></li>
</ul>
<h4 id="バーコードリーダっぽく四角い枠をつける"><a href="#%E3%83%90%E3%83%BC%E3%82%B3%E3%83%BC%E3%83%89%E3%83%AA%E3%83%BC%E3%83%80%E3%81%A3%E3%81%BD%E3%81%8F%E5%9B%9B%E8%A7%92%E3%81%84%E6%9E%A0%E3%82%92%E3%81%A4%E3%81%91%E3%82%8B">バーコードリーダっぽく四角い枠をつける</a></h4>
<p>これ。</p>
<p><img width="325" alt="スクリーンショット 2019-09-18 9.49.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/1e030b9c-cdff-41ef-5a90-10e50c03f3ad.png"></p>
<p><code>#camera-area</code>内にdivをもたせて表示させている</p>
<pre><code class="html"><template>
<div class="dialog modal is-active" v-if="active">
<div class="modal-background"></div>
<div class="modal-content">
<div id="camera-area" class="camera-area">
<!-- 青い四角のDIV -->
<div class="detect-area"></div>
</div>
</div>
<button class="modal-close is-large" aria-label="close" @click.prevent.stop="onClickCancel"></button>
</div>
</template>
<style lang="scss">
.camera-area {
margin: auto;
overflow: hidden;
height: 300px;
width: 300px;
/* relativeに設定 */
position: relative;
video, canvas {
margin-top: -50px;
width: 300px;
height: 400px;
}
/* 検出範囲のサイズに合わせ枠線を引く */
.detect-area {
position: absolute;
top: 30%;
bottom: 30%;
left: 10%;
right: 10%;
border: 2px solid #0000ff;
}
}
</style>
</code></pre>
<h4 id="解析中っぽく緑の枠を出す"><a href="#%E8%A7%A3%E6%9E%90%E4%B8%AD%E3%81%A3%E3%81%BD%E3%81%8F%E7%B7%91%E3%81%AE%E6%9E%A0%E3%82%92%E5%87%BA%E3%81%99">解析中っぽく緑の枠を出す</a></h4>
<p>読み取っている箇所を表示できるよう解析中のコールバックがある。<br />
<a target="_blank" rel="nofollow noopener" href="https://kuroeveryday.blogspot.com/2017/12/barcode-scaner-with-quaggajs.html">こちらの記事</a>を参考に、解析中の状況を表示する。</p>
<pre><code class="html"><script lang="ts">
@Component
export default class ModalBarcodeReader extends Vue {
private initQuagga() {
this.Quagga = require("quagga");
// 解析中に呼び出される処理を設定
this.Quagga.onProcessed(this.onProcessed);
this.Quagga.onDetected(this.onDetected);
// ...
}
/**
* バーコード読み取り中時の処理
*/
private onProcessed(data) {
const ctx = this.Quagga.canvas.ctx.overlay;
const canvas = this.Quagga.canvas.dom.overlay;
if (!data) return;
// 認識したバーコードを緑の枠で囲む
if (data.boxes) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const hasNotRead = box => box !== data.box;
data.boxes.filter(hasNotRead).forEach(box => {
this.Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, ctx, { color: "green", lineWidth: 2 });
});
}
// 読み取ったバーコードを青の枠で囲む
if (data.box) {
this.Quagga.ImageDebug.drawPath(data.box, { x: 0, y: 1 }, ctx, { color: "blue", lineWidth: 2 });
}
// 読み取ったバーコードに赤い線を引く
if (data.codeResult && data.codeResult.code) {
this.Quagga.ImageDebug.drawPath(data.line, { x: "x", y: "y" }, ctx, { color: "red", lineWidth: 3 });
}
}
}
</script>
<style lang="scss">
.camera-area {
/* ... */
/* オーバーレイ */
.drawingBuffer {
position: absolute;
left: 0;
}
}
</style>
</code></pre>
<p>以下のサンプル画像のように、<br />
読み取ったバーコードの枠を囲ったり、線を引いたりもできる(<em>´ω`</em>)</p>
<p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/8bfadb8e-0cdd-bc42-f673-762e64246810.png" alt="スクリーンショット 2019-09-18 10.13.43.png" /></p>
<h2 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h2>
<p>Nuxt.jsアプリでも<a target="_blank" rel="nofollow noopener" href="https://serratus.github.io/quaggaJS/">QuaggaJS</a>で簡単にバーコードリーダが作れる(<em>´ω`</em>)</p>
<p>ただ、getUserMedia()にも、iOSのPWAには罠が。。</p>
<h2 id="こんなのつくってます!!"><a href="#%E3%81%93%E3%82%93%E3%81%AA%E3%81%AE%E3%81%A4%E3%81%8F%E3%81%A3%E3%81%A6%E3%81%BE%E3%81%99%21%21">こんなのつくってます!!</a></h2>
<p>バーコードリーダ機能もある積読用の読書管理アプリ<br />
『積読ハウマッチ』をリリースしました!<br />
<a target="_blank" rel="nofollow noopener" href="https://tsundoku.site">積読ハウマッチ</a>は、Nuxt.js+Firebaseで開発してます!</p>
<p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/572d4947-f40b-e4dc-1c9c-bc584cd2a66c.png" width="200"/></p>
<p>もしよかったら、遊んでみてくださいヽ(=´▽`=)ノ</p>
<p>要望・感想・アドバイスなどあれば、<br />
公式アカウント(<a target="_blank" rel="nofollow noopener" href="https://twitter.com/MemoryLoverz">@MemoryLoverz</a>)や開発者(<a target="_blank" rel="nofollow noopener" href="https://twitter.com/kira_puka">@kira_puka</a>)まで</p>
<h2 id="参考にしたサイト"><a href="#%E5%8F%82%E8%80%83%E3%81%AB%E3%81%97%E3%81%9F%E3%82%B5%E3%82%A4%E3%83%88">参考にしたサイト</a></h2>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://serratus.github.io/quaggaJS/">QuaggaJS, an advanced barcode-reader written in JavaScript</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://serratus.github.io/quaggaJS/v1.0.0-beta.1/examples/sandbox/">Quagga Sandbox</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/serratus/quaggaJS/blob/master/example/live_w_locator.html">quaggaJS/live_w_locator.html at master · serratus/quaggaJS</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://watchcontents.com/quaggajs-barcode-reader/">QuaggaJSを使ったバーコードリーダ実装 | WatchContents</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://kuroeveryday.blogspot.com/2017/12/barcode-scaner-with-quaggajs.html">Quagga.jsを使ってブラウザ上からJavaScriptでバーコードを読み取る | Black Everyday Company</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/1pp0/items/a3f0ea14910e25f49878">PWAでカメラを使うためiOSとAndroidで異なるmanifestを読み込む - Qiita</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/MediaDevices/getUserMedia">MediaDevices.getUserMedia() - Web API | MDN</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/MediaDevices/enumerateDevices">MediaDevices.enumerateDevices() - Web API | MDN</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://app.codegrid.net/entry/2017-get-user-media-1">ブラウザからメディアデバイスを操る - getUserMedia()の基本 | CodeGrid</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/mm_sys/items/6e5e927ef75ab82fa8d3#webcodecamjs%E3%82%92%E5%B1%95%E9%96%8B">ブラウザでバーコード/QRコードリーダー【実装・カスタマイズ編】 - Qiita</a></li>
<li><a target="_blank" rel="nofollow noopener" href="http://fow.minim.ne.jp/?p=383">WebサイトからスマートフォンのカメラでQRコードを読み取る – JavaScript (Android、iOS、PC対応) – flow of water</a></li>
<li><a target="_blank" rel="nofollow noopener" href="http://kujundev.wp.xdomain.jp/?p=437">バーコード読み取り | KuJunDev</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/k-murayama/items/eddcc974bd0dd3a214ed">Javascriptのバーコードライブラリ - Qiita</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/1pp0/items/a3f0ea14910e25f49878">PWAでカメラを使うためiOSとAndroidで異なるmanifestを読み込む - Qiita</a></li>
</ul>
きらぷか@積読ハウマッチ/SSSAPIなど