この記事の内容は、React コンポーネントを使用して写真を撮影し、アップロードする写真を選択することに関するものです。必要な方は参考にしていただければ幸いです。
プロジェクトは少し前に再構築され、SSR プロジェクトに変更されましたが、以前使用されていた画像選択アップロード コンポーネントは SSR (サーバーサイド レンダー) をサポートしていませんでした。そこで調査を行ったところ、多くのツールを見つけました。しかし、大きすぎるもの、使いにくいもの、使用ニーズを満たさないものもあります。 h5 モバイル画像アップロード コンポーネントを自分で作成することにしました。画像のアップロードは比較的一般的なニーズです。PC 版では問題ありませんが、モバイル版は特に簡単ではありません。以下に、プロセスにおけるいくつかの重要な問題を簡単に記録します。
重要なポイント
1. input について
選択機能は タグを使用して実装されます。属性 accept='image/*', :capture は、カメラ -- カメラ -- カメラ -- マイク -- 録画など、システムのデフォルトのデバイスをキャプチャできることを意味します。 Capture="camera" を設定するとデフォルトでカメラが使用されますが、機種によってはカメラを呼び出すことができない問題があるため、ここでは設定しません。複数の選択に加えて、onchange イベントのコールバック関数を許可します。最終的な入力はおそらく次のようになります:
<input type='file' className={classes.picker} accept='image/*' multiple capture="camera" onChange={this.onfileChange} />
もちろん、この入力は醜いですが、「opacity:0」を設定して配置することで、必要な選択ボタンのスタイルで上書きできます。もう少し華やかにしましょう。
画像を選択した後にプレビューできることは一般的な機能です。ここではスタイルについては置いておいて、コードの実装についてのみ説明します。 onchange のコールバック関数では、e.target.files を通じて選択したファイルを取得できますが、そのファイルをページ上に表示することはできません。通常は、reader.readAsDataURL(file) を使用して Base64 に変換して表示します。それはページ上にあります。ここでは9マスのグリッド表示を使用しており、それぞれの写真がキャンバスになります。画像のアスペクト比の違いを考慮して、最初に Reader.readAsDataURL(file) を通じて Base64 ファイルを取得します。次に、9 正方形グリッドのキャンバス アスペクト比で描画された画像を作成し、画像コンテンツが歪みなくキャンバス全体をカバーできるようにします。
fileToCanvas (file, index) {//文件 let reader = new FileReader(); reader.readAsDataURL(file); reader.onload = (event) => { let image = new Image(); image.src = event.target.result; image.onload = () => { let imageCanvas = this['canvas' + index].getContext('2d'); let canvas = { width: imageCanvas.canvas.scrollWidth * 2, height: imageCanvas.canvas.scrollHeight * 2 }; let ratio = image.width / image.height; let canvasRatio = canvas.width / canvas.height; let xStart = 0; let yStart = 0; let renderableWidth; let renderableHeight; if (ratio > canvasRatio) { // 横向过大,以高为准,缩放宽度 let hRatio = image.height / canvas.height; renderableHeight = image.height; renderableWidth = canvas.width * hRatio; xStart = (image.width - renderableWidth) / 2; } if (ratio < canvasRatio) { // 横向过小,以宽为准,缩放高度 let wRatio = image.width / canvas.width; renderableWidth = image.width; renderableHeight = canvas.height * wRatio; yStart = (image.height - renderableHeight) / 2; } imageCanvas.drawImage(image, xStart, yStart, renderableWidth, renderableHeight, 0, 0, canvas.width * 2, canvas.height); }; }; }
一部のモデルで写真を撮影する場合、onchange イベントを通じて取得されるファイルは blob
(Xiaomi 6 など) ) この時点で blob.type
拡張子を手動で決定します。
ios 写真をアップロードすると、ローカル ファイルが正常に回転されていないことがわかります。ここで詳しく説明します。興味があれば検索してみてください。したがって、向きを検出し、画像を回転して通常の向きに戻す必要があります。 Exif.js など、方向を取得するための既製のライブラリが多数あります。しかし、このライブラリは少し大きいので、この小さな要件のために導入する価値はないようです。 stackoverflow で画像の方向を取得するための既製のコードが多数あります。
少し変更:
getOrientation (file) { return new Promise((resolve, reject) => { let reader = new FileReader(); reader.onload = function (e) { //e.target.result为base64编码的文件 let view = new DataView(e.target.result); if (view.getUint16(0, false) !== 0xffd8) { return resolve(-2); } let length = view.byteLength; let offset = 2; while (offset < length) { let marker = view.getUint16(offset, false); offset += 2; if (marker === 0xffe1) { let tmp = view.getUint32(offset += 2, false); if (tmp !== 0x45786966) { return resolve(-1); } let little = view.getUint16(offset += 6, false) === 0x4949; offset += view.getUint32(offset + 4, little); let tags = view.getUint16(offset, little); offset += 2; for (let i = 0; i < tags; i++) { if (view.getUint16(offset + i * 12, little) === 0x0112) { return resolve(view.getUint16(offset + i * 12 + 8, little)); } } } else if ((marker & 0xff00) !== 0xff00) { break; } else { offset += view.getUint16(offset, false); } } return resolve(-1); }; reader.readAsArrayBuffer(file.slice(0, 64 * 1024)); }); }
//戻り値: 1--normal、-2--non-jpg、-1--unknown
通常の画像の向きは1のはずなので、ファイルをcanvasに変換し、canvasのtransformメソッドを使って変形しますので、参考にしてください。最後に、canvas.toDataURL('') を通じて Base64 エンコードの通常の方向で Base64 イメージを取得し、アップロードのために Base64 を BLOB に変換します。 ##image アップロード、この部分は比較的簡単です。 FormData の形式でファイルをアップロードするだけです。上記のコードは一部の関数の擬似コードにすぎず、すべての関数の最終実装ではありません。
できることならいろいろ試してみると、最終的には多くのことを学んだことに気づくでしょう。しかし、他の人のホイールは依然として役に立ちます2333。
以上がH5 は反応コンポーネントを使用して写真を撮り、アップロードする写真を選択しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。