背景少し前にブラウザカメラの取得とスキャンコード認識の機能を作りました。その際の知識ポイントと具体的なコード実装を整理して記事の内容にまとめました。 この記事では主に、 成果を達成するこの例では、ホームページと QR コードスキャンページの 2 つのメインページがあります。具体的な実装効果は、次の図に示されています。
オンライン体験: https://dragonir.github.io/h5-scan-qrcode ヒント: カメラデバイスを備えたブラウザで縦向きモードでアクセスする必要があります。携帯電話の横画面と縦画面の検出に関するその他のヒントについては、私の別の記事「Gokudō ゲームにおけるフロントエンドの知識」をご覧ください。 技術紹介WebRTC API WebRTC (Web Real-Time Communications) は、ネットワーク アプリケーションまたはサイトが、仲介者の助けを借りずにブラウザー間で 3 つの主なインターフェース:
WebRTC アダプター
コア API Web ページは、カメラを呼び出すために これは navigator.mediaDevices.getUserMedia(制約) .then(関数(ストリーム) { // このストリームを使用する }) .catch(関数(エラー) { // エラーを処理する }) QRコード解析ライブラリ const code = jsQR(imageData, 幅, 高さ, オプション); if (コード) { console.log('QRコードが見つかりました!', code); } コードの実装プロセスコードスキャンのプロセス全体を下図に示します。ページが初期化され、まずブラウザが 以下の内容はプロセスを分割し、それぞれ対応する機能を実装します。 ページ構造まず、主に
<テンプレート> <div class="スキャナー" ref="スキャナー"> <!-- プロンプト ボックス: 互換性のないブラウザでプロンプトを表示するために使用されます--> <div class="banner" v-if="showBanner"> <i class="close_icon" @click="() => showBanner = false"></i> <p class="text">現在のブラウザでコードをスキャンできない場合は、別のブラウザに切り替えてお試しください</p> </div> <!-- スキャンコードボックス: スキャンコードアニメーションを表示します--> <div class="カバー"> <p class="line"></p> <span class="square 左上"></span> <span class="square 右上"></span> <span class="square 右下"></span> <span class="square 左下"></span> <p class="tips">QR コードをボックスに入れると自動的にスキャンされます</p> </div> <!-- ビデオ ストリームの表示 --> <ビデオ v-show="showPlay" クラス="ソース" ref="ビデオ" :width="ビデオWH.width" :height="ビデオWH.height" コントロール </ビデオ> <canvas v-show="!showPlay" ref="canvas" /> <button v-show="showPlay" @click="run">開始</button> </div> </テンプレート> 方法: 描画
// 線を描く drawLine (begin, end) { パスの開始位置を指定します。 this.canvas.moveTo(begin.x, begin.y); this.canvas.lineTo(終了x、終了y); キャンバスの線幅を設定します。 this.canvas.strokeStyle = this.lineColor; キャンバスのストローク }, // 描画ボックス (場所) { if (this.drawOnfound) { this.drawLine(location.topLeftCorner、location.topRightCorner); this.drawLine(location.topRightCorner, location.bottomRightCorner); this.drawLine(location.bottomRightCorner, location.bottomLeftCorner); this.drawLine(location.bottomLeftCorner、location.topLeftCorner); } }, 方法: 初期化
// 初期化セットアップ () { // ブラウザが MediaDevices.getUserMedia() に搭載されたメソッドをサポートしているかどうかを判定します if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { this.previousCode = null; this.parity = 0; this.active = true; this.canvas = this.$refs.canvas.getContext("2d"); // カメラモードを取得します。デフォルト設定は背面カメラです。const facingMode = this.useBackCamera ? { exact: 'environment' } : 'user'; // カメラビデオ処理 const handleSuccess = stream => { if (this.$refs.video.srcObject !== 未定義) { this.$refs.video.srcObject = ストリーム; } そうでない場合 (window.videoEl.mozSrcObject !== 未定義) { this.$refs.video.mozSrcObject = ストリーム; } それ以外の場合 (window.URL.createObjectURL) { this.$refs.video.src = window.URL.createObjectURL(ストリーム); } それ以外の場合 (window.webkitURL) { this.$refs.video.src = window.webkitURL.createObjectURL(ストリーム); } それ以外 { this.$refs.video.src = ストリーム; } // ユーザーにプログレス バーをドラッグさせたくない場合は、playsinline 属性を直接使用できます。webkit-playsinline attribute this.$refs.video.playsInline = true; const playPromise = this.$refs.video.play(); 再生Promise.catch(() => (this.showPlay = true)); // ビデオの再生が開始されたら、識別のためにコードを定期的にスキャンします。playPromise.then(this.run); }; // ビデオストリームをキャプチャするnavigator.mediaDevices .getUserMedia({ ビデオ: { 向きモード } }) .then(ハンドル成功) .catch(() => { ナビゲーター.メディアデバイス .getUserMedia({ビデオ: true }) .then(ハンドル成功) .catch(エラー => { this.$emit("error-captured", error); }); }); } }, 方法: 定期スキャン 走る () { アクティブの場合 // ブラウザは、次の再描画の前にループ内でスキャン メソッド requestAnimationFrame(this.tick) を呼び出します。 } }, メソッド: 成功コールバック // QRコード認識成功イベント処理が見つかりました(コード){ if (this.previousCode !== コード) { this.previousCode = コード; } それ以外の場合 (this.previousCode === code) { this.parity += 1; } (このパリティ>2)の場合{ this.active = this.stopOnScanned ? false の場合、 true; this.parity = 0; this.$emit("code-scanned", コード); } }, 方法: 停止 // 終止符 fullStop () { (this.$refs.video && this.$refs.video.srcObject) の場合 { // ビデオ ストリーム シーケンス トラックを停止します。this.$refs.video.srcObject.getTracks().forEach(t => t.stop()); } } 方法: スキャン
// 定期的なコードスキャンと認識 tick () { // ビデオは準備段階にあり、十分なデータが読み込まれています if (this.$refs.video && this.$refs.video.readyState === this.$refs.video.HAVE_ENOUGH_DATA) { // キャンバスにビデオの描画を開始します。this.$refs.canvas.height = this.videoWH.height; this.$refs.canvas.width = this.videoWH.width; this.canvas.drawImage(this.$refs.video, 0, 0, this.$refs.canvas.width, this.$refs.canvas.height); // getImageData() はキャンバス上の指定された四角形のピクセル データをコピーします。const imageData = this.canvas.getImageData(0, 0, this.$refs.canvas.width, this.$refs.canvas.height); code = false とします。 試す { // QR コードを認識する code = jsQR(imageData.data, imageData.width, imageData.height); } キャッチ (e) { コンソールエラー(e); } // QRコードが認識された場合、長方形のボックスを描画します if (code) { this.drawBox(コードの場所); // 成功したイベント処理を識別します this.found(code.data); } } これを実行してください。 }, 親コンポーネント
ページ構造 <テンプレート> <div class="scan"> <!-- ページナビゲーションバー--> <div class="nav"> <a class="close" @click="() => $router.go(-1)"></a> <p class="title">QR コードをスキャン</p> </div> <div class="スクロールコンテナ"> <!-- スキャンコードサブコンポーネント--> <スキャナー v-on:code-scanned="コードスキャン済み" v-on:error-captured="エラーキャプチャ済み" :スキャン時に停止="true" :draw-on-found="true" :responsive="false" /> </div> </div> </テンプレート> 親コンポーネントメソッド Scaner を '../components/Scaner' からインポートします。 エクスポートデフォルト{ 名前: 'スキャン'、 コンポーネント: スキャナー }, データ () { 戻る { エラーメッセージ: "", スキャン済み: "" } }, メソッド: { コードスキャン済み(コード) { this.scanned = コード; タイムアウトを設定する(() => { alert(`コードをスキャンして解析に成功しました: $[code]`); }, 200) }, errorCaptured(エラー) { スイッチ (エラー.name) { ケース「NotAllowedError」: this.errorMessage = "カメラの許可が拒否されました。"; 壊す; 「NotFoundError」の場合: this.errorMessage = "接続されたカメラがありません。"; 壊す; ケース「NotSupportedError」: this.errorMessage = 「このページは安全でないコンテキストで提供されているようです。」; 壊す; ケース「NotReadableError」: this.errorMessage = 「カメラにアクセスできませんでした。すでに使用されていますか?」; 壊す; ケース「OverconstrainedError」: this.errorMessage = "制約はインストールされているカメラと一致しません。"; 壊す; デフォルト: this.errorMessage = "不明なエラー: " + error.message; } コンソールエラー(このエラーメッセージ); alert('カメラの呼び出しに失敗しました'); } }, マウントされた(){ var str = navigator.userAgent.toLowerCase(); var ver = str.match(/cpu iphone os (.*?) like mac os/); // テストの結果、iOS 10.3.3未満のシステムではカメラを正常に呼び出すことができません if (ver && ver[1].replace(/_/g,".") < '10.3.3') { alert('カメラの呼び出しに失敗しました'); } } 完全なコード
要約するアプリケーション拡張機能ブラウザ経由でカメラを呼び出してスキャン・識別することで、以下のような機能が実現できると思います。 ブラウザ側のコードをスキャンすることで、他にどんな
互換性
参考文献 [1] WebRTCで静止画を撮影する [2] mediaDevices APIを使用してJavaScriptでカメラを選択する [3] JavaScriptを使用してデバイスの前面カメラと背面カメラにアクセスする方法 著者: dragonir 記事URL: https://www.cnblogs.com/dragonir/p/15405141.html Vue のブラウザ側コードスキャン機能の実装に関するこの記事はこれで終わりです。より関連性の高い vue ブラウザコードスキャンのコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き閲覧してください。皆様、今後とも 123WORDPRESS.COM を応援してください。 以下もご興味があるかもしれません:
|
<<: docker に openjdk をインストールして jar パッケージを実行する方法
>>: HTML テーブル マークアップ チュートリアル (29): セルのライト境界線の色属性 BORDERCOLORLIGHT
この記事の例では、要素のマウスドラッグ効果を実現するためのvue+tsの具体的なコードを参考までに共...
HTML にはデータ属性が含まれていることがよくあります。これらは HTML5 のカスタム属性です。...
1. 事前に準備する便宜上、ここで 2 つのテーブルを作成し、そこにいくつかのデータを追加します。果...
目次アプリケーションシナリオ簡単に言えば、カスタム指示基本概念グローバルカスタマイズローカルカスタマ...
1. MySQL アーカイブ (解凍版) をダウンロードするURL: https://downloa...
CSS スタイル仕様1. クラスセレクター2. タグセレクター3. IDセレクター4. CSSスタイ...
Vue コンポーネントは接続されているため、コンポーネント間で値を渡す必要があるのは避けられません...
バグ図のように、削除文とパラメータをデータベースにコピーして実行し、2つのデータを削除しようとしたの...
1. 公式 Web サイトから MySQL 5.7 インストール パッケージ (mysql-5.7....
最近何かをするときにラベル タグを使用しました。以前はラベル タグをほとんど使用していなかったため、...
第一に: CSSを導入する4つの方法CSS を導入する方法には、インライン スタイル、埋め込みスタイ...
SFTPの概念sftp は、安全なファイル転送プロトコルである Secure File Transf...
最近、テスト サーバーのオペレーティング システムを Cent0S 7.5 にアップグレードし、Py...
ミックスインは、コンポーネントに分散された再利用可能な機能を柔軟な方法で提供します。 Mixin オ...
目次ブラウザのレンダリングメカニズムリフローと再塗装リフロー逆流を引き起こす行為:再描画再描画を引き...