元のアドレス: github.com/whinc/blog/…
最近、コメントを投稿するリクエストを受け取りました。ユーザーはコメントを入力し、写真を撮ったり、アルバムから写真を選択してアップロードしたりできます。つまり、テキストと画像のコメントがサポートされています。この要件は、H5 プログラムとミニ プログラムの両方に同時に実装する必要があるため、画像を処理するための多くの場所が必要になります。この記事では、H5 側での画像処理の実践についてまとめます。プロジェクトのコードは Vue フレームワークに基づいており、フレームワークの影響を避けるために、説明のためにすべてのコードをネイティブ API 実装に変更しました。同時に、その他の追加の詳細と機能 (プレビュー、トリミング) が追加されています。 、アップロードの進捗状況など)をここでは省略し、画像処理に関連する重要なアイデアとコードのみを紹介します。ミニ プログラムの実装は H5 と似ているため、繰り返しません。ミニ プログラムの実装コードは記事の最後に添付されています。
写真<input> タグを使用し、type を file に設定してファイルを選択し、accept を image/* に設定してファイル タイプとカメラを選択し、multiple を設定して複数の選択をサポートします。変更イベントをリッスンして、選択されたファイルのリストを取得します。各ファイルは BLOB タイプです。
<input type=file accept=image/* multiple /> <img class=preivew /> <script type=text/javascript> function onFileChange (event) { const files = Array.prototype.slice.call(event.target.files) ) files.forEach(file => console.log('ファイル名:', file.name)) } document.querySelector('input').addEventListener('change', onFileChange) </script>画像プレビュー
URL.createObjectURL メソッドは、ローカル リソース オブジェクトを指すローカル URL パスを作成できます。このインターフェイスは、選択した画像のアドレスを作成して表示するために以下で使用されます。
function onFileChange (event) { const files = Array.prototype.slice.call(event.target.files) const file = files[0] document.querySelector('img').src = window.URL.createObjectURL(file) }画像の回転
カメラで撮影した写真は、撮影時のカメラの構え方によって回転してしまう場合があり、補正が必要になります。回転を修正するには、画像の回転情報を知る必要があります。ここでは、撮影時のカメラの方向を含む画像の EXIF メタデータを読み取ることができる exif-js と呼ばれるライブラリを使用します。画像の情報を計算することができます。
以下はEXIF回転フラグビットで、合計8種類ありますが、カメラを通して撮影する場合は、それぞれカメラの通常、時計回りの180°に対応する1、3、6、8のみが生成されます。回転、90°反時計回り、および90°で撮影した写真。
したがって、画像の回転角度を修正するには、画像のEXIF回転フラグを読み取って回転角度を決定し、キャンバス上で画像を回転し、新しい画像を再エクスポートするだけで済みます。キャンバスの回転操作については「キャンバス画像の回転と姿勢反転のロック解除」の記事を参照してください。次の関数は、画像ファイルの回転角度補正を実装し、画像ファイルを受け取り、補正された新しい画像ファイルを返します。
/** * 画像の回転角度の問題を修正 * @param {file} 元の画像 * @return {Promise} 解決された約束 修正された新しい画像を返します */function fixImageOrientation (file) { return new Promise((resolve, detect) => { // 画像を取得します const img = new Image() = window.URL.createObjectURL(file); img.onload = () => { // 画像のメタデータを取得します (EXIF 変数は、導入された exif-js ライブラリによって公開されるグローバル変数です) EXIF.getData(img, function() { // 画像の回転フラグを取得します var Orientation = EXIF.getTag(this, Orientation); // 回転角度に従ってキャンバス上の画像を回転します if (orientation === 3 || Orientation === 6 || Orientation === 8) { const Canvas = document.createElement(canvas); const ctx = Canvas.getContext(2d); switch (orientation) { case 3: // 180 度回転 Canvas.width = img.height; (180 * Math.PI) / 180); ctx.drawImage(img, -img.width, -img.height, img.width, img.height); ケース 6: // 90 度回転 Canvas.width = img.height = img.rotate((90 * Math.PI) / 180); ctx.drawImage(img, 0, -img.height, img.width, img.height); // -90 度回転 Canvas.width = img.height; ctx.rotate((-90 * Math.PI) / 180); .width, img.height); } // 新しい画像を返します Canvas.toBlob(file =>solve(file), 'image/jpeg', 0.92) } else { returnsolve(file) } });画像圧縮
現在、携帯電話のカメラ効果はますます向上しており、それに伴い写真のサイズも大きくなり、簡単に数 MB、場合によっては 10 MB を超えることもあります。元の写真を直接アップロードするのは遅いですが、簡単にアップロードできます。失敗し、背景にもリクエストボディのサイズに制限があるため、その後の画像表示の読み込みも遅くなります。フロントエンドで画像を圧縮してアップロードすれば、これらの問題は解決できます。
次の関数は画像圧縮を実装します。その原理は、拡大縮小された画像をキャンバス上に描画し、最終的に圧縮された画像をキャンバスからエクスポートすることです。画像圧縮を制御するには 2 つの方法があります。1 つは画像のズーム率を制御する方法、もう 1 つはエクスポートされる画像の品質を制御する方法です。
/** * 圧縮画像 * @param {file} 入力画像 * @returns {Promise} 解決されたプロミス 新しい圧縮画像を返します */function compressImage(file) { return new Promise((resolve, detect) => { // Get画像 (画像の読み込みは画像の幅と高さを取得することです) const img = new Image() = window.URL.createObjectURL(file); img.onerror => raise(error); img.onload = () => { // キャンバスの幅と高さ const CanvasWidth = document.documentElement.clientWidth * window.devicePixelRatio; const CanvasHeight = document.documentElement.clientHeight * window.devicePixelRatio;要因 // ここでは、すべての画像コンテンツが確実に表示されるように、より大きな水平および垂直スケール係数をスケール係数として採用します。 constscaleX = CanvasWidth / img.width; constscaleY = CanvasHeight / img.height; // 倍率に従って元の画像を拡大縮小してキャンバスに描画します const Canvas = document.createElement ('キャンバス'); const ctx = Canvas.getContext(2d); Canvas.height = const imageWidth = img.width * スケール; const imageHeight = img.height * スケール; const dx = (canvasWidth - imageHeight) / 2; ); // 新しい画像をエクスポート // 画像の MIME タイプを「image/jpeg」として指定し、品質を渡しますエクスポートされる画像の品質を制御し、画像圧縮を実装します。 constquality = 0.92 Canvas.toBlob(file =>solve(tempFile), image/jpeg,quality) });}画像のアップロード
FormData を通じてフォーム データを作成し、ajax POST リクエストを開始する次の関数は、ファイルのアップロードを実装します。
注: FormData データを送信するとき、ブラウザは Content-Type を適切な値に自動的に設定します。Content-Type を設定する必要はありません。設定しないと、HTTP リクエスト本文の区切り文字の境界がブラウザによって生成されるため、エラーが報告されます。手動で設定することはできません。
/** * ファイルをアップロードします* @param {File} file アップロードするファイル* @returns {Promise} アップロードが成功した場合は解決された Promise を返し、そうでない場合は拒否された Promise を返します */function UploadFile (file) { return new Promise((resolve , accept) = > { // フォームデータを準備する const formData = new FormData() formData.append('file', file) // リクエストを送信する const xhr = new XMLHttpRequest() xhr.open('POST', UploadUrl) xhr.onreadystatechange = function () { if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {solve(JSON.parse(this.responseText)) } else {拒否(this.responseText) } } xhr.send(formData) })}まとめ
上記の補助関数を使用すると、処理は非常に簡単になります。最終的な呼び出しコードは次のとおりです。
function onFileChange (event) { const files = Array.prototype.slice.call(event.target.files) const file = files[0] // 画像の回転を修正 fixImageOrientation(file).then(file2 => { // プレビューを作成画像 document.querySelector('img').src = window.URL.createObjectURL(file2) // 圧縮 return compressImage(file2) }).then(file3 => { // プレビュー画像を更新 document.querySelector('img').src = window.URL.createObjectURL(file3) // アップロード return UploadFile(file3) }).then(data => { console.log('アップロード成功') }).catch(error => { console.error('アップロード失敗') })}
H5 は、キャンバスの助けを借りて、複雑な画像処理をブラウザーで実装できるインターフェイスを提供します。この記事では、モバイル端末上で H5 に画像をアップロードするシナリオでの画像処理の実践方法をまとめます。将来同様のニーズが発生した場合に部分的に参照してください。
小さなプログラム実装リファレンスを添付します。
// 写真を撮る wx.chooseImage({ sourceType: [camera], success: ({ tempFiles }) => { const file = tempFiles[0] // 画像を処理する }});/** * 画像を圧縮* @param { Object } params * filePath: String 入力画像パス * success: 関数 圧縮が成功するとコールバックされ、新しい圧縮画像パスを返します * failed: 関数圧縮失敗時のコールバック */compressImage({ filePath, success, failed }) { // 画像の幅と高さを取得 wx.getImageInfo({ src: filePath, success: ({ width, height }) => { const systemInfo = wx .getSystemInfoSync (); const CanvasWidth = systemInfo.screenWidth; //キャンバスのサイズを更新します this.setData({ CanvasWidth, CanvasHeight }) // 拡大縮小率を計算します constscaleX = CanvasWidth / width; constscaleY = CanvasHeight / height; *scale ; const imageHeight = height *scale; // 拡大縮小された画像をキャンバスに描画します const ctx = wx.createCanvasContext(hidden-canvas); dx = (canvasWidth - imageWidth) / 2; let dy = (canvasHeight - imageHeight) / 2; ctx.drawImage(filePath, dx, dy, imageWidth, imageHeight); // エクスポート圧縮された画像を一時ファイルに保存 wx.canvasToTempFilePath({ CanvasId: hidden-canvas, width: CanvasWidth, height: CanvasHeight, destWidth: CanvasWidth, destHeight: CanvasHeight, fileType: jpg, 品質: 0.92, success: ({ tempFilePath }) => { // キャンバスを非表示 this.setData({ CanvasWidth: 0, CanvasHeight: 0 } ) // 圧縮が完了しました success({ tempFilePath }) }、失敗: error => { //キャンバスを非表示にする this.setData({ CanvasWidth: 0, CanvasHeight: 0 }) 失敗(エラー) } }) }; 失敗: エラー => { 失敗(エラー) }; }ファイルをアップロード*/uploadFile({ UploadUrl, filePath, onData, onError }) { wx.uploadFile({ url: UploadUrl filePath: filePath, name:ファイル、ヘッダー: { Cookie: cookie }、成功: res => { if (res.statusCode === 200) { onData(res.data) } else { onError(res) } }、失敗: error => { onError(エラー); } });}要約する
上記は、画像の回転、圧縮、アップロードの機能を実現するために編集者が紹介した HTML5 と小さなプログラムです。ご質問があれば、メッセージを残してください。編集者が返信します。間に合ったあなた。また、VeVb武道サイトを応援してくださった皆様、誠にありがとうございました!