画像のトリミングとアップロードは、ユーザーエクスペリエンスに非常に適した機能であるだけでなく、特定の画像サイズを統一し、Webサイトのレイアウトを最適化し、一石二鳥の効果もあります。
要件はシンプルで、ブラウザーで画像を切り取ってサーバーにアップロードするだけです。
私が最初に考えた方法は、画像とトリミングパラメータ(x、y、スケール、回転)をサーバーにアップロードすることで、サーバーが画像処理を行うので、とても簡単です。
しかし、これは開発のトレンドに沿っていません: フロントエンドでできる処理はフロントエンドにやらせます。
トレンドに妥協した結果、フロントエンドはますます複雑になります。
最初は、ブラウザが画像を読み取って生成できるとは思いませんでした。考えてみてください。「クリックしてコピー」などの単純な機能を実行するには、Flash ブラウザを使用する必要があり、権限はそれほど大きくありません。
画像をローカルで処理する限り、基本的には Flash を使用します。コピーするだけです。API はありません。画像を変更できても、アップロード パスを変更する方法がわかりません。さらに重要なのは、私は Flash について何も知りません。
幸いなことに、私たちの Web サイトは IE9 以下のブラウザーを完全に放棄し、最新の HTML5 ブラウザーとのみ互換性があります。 (Opera や Microsoft でさえ Webkit カーネル路線をたどり始めており、Chrome を追随する傾向にあります。) 私は HTML5 に期待するしかないので、少し調べてみたところ、次のプロセスが実現可能であることがわかりました。
st=>start: 原图片 File 对象e=>end: 上传裁剪后的Blob对象op=>operation: 初始化Cropper 图片Base64预览op1=>operation: 根据Cropper裁剪参数绘制Canvas(Base64)op2=>operation: Base64转Blob对象st->op->op1->op2->e
各リンクについては、以下で詳しく説明します。
各画像ファイルの処理の始まりは onchange イベントによって開始されます
<script> function handler(e){ var originPhoto = e.target.files[0]; // IE10+ 单文件上传取第一个 window.originFileType = originPhoto.type; //暂存图片类型 window.originFileName = originPhoto.name; //暂存图片名称 ... }</script><input type="file" name="demo" onchange='handler(event)' accept="image/*" ><img id="preview"><button onclick="cropAndUpload()">确定并上传</button>
ここでは非常に使いやすいライブラリ Cropper.js を紹介します
https:/ /github .com/fengyuanchen/cropper
マスクの生成、トリミングパラメータの取得、キャンバスの出力...そしてそれは非常に軽量で、圧縮された CSS コードと JS コードはわずか 30 KB です。 JQuery をベースにしているため、JQuery の導入は少し複雑になる可能性があります。しかし、現在 JQuery を使用していない Web サイトはどれでしょうか?
IE9+と互換性があり、優れたモバイルエクスペリエンスを備え、タッチズームやドラッグに応答できます。以下は Android 4.4 のネイティブブラウザでのプレビュー画像です
function handler(event){ ... var URL = window.URL || window.webkitURL , originPhotoURL; originPhotoURL = URL.createObjectURL(originPhoto); //Base64 $('#preview').cropper({ aspectRatio: 1 / 1, // 固定裁剪比例1:1,裁剪后的图片为正方形 }).cropper('replace', originPhotoURL); // 动态设置图片预览}
Cropper.js には、Canvas を生成するメソッド getCroppedCanvas が用意されており、生成されるキャンバスのサイズを指定できます。
または、getData に基づいてトリミング情報 (回転とスケーリングを含む) を取得し、ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) を使用して手動で描画します。後者の方が自由ですが、既製の方法があるので、それを使用してください。
function cropAndUpload(){ // 此处注意,生成的Canvas长宽比应与之前规定的裁剪比例一致 // 否则生成的图片会有失真 var size = { width:100, height:100 } var croppedCanvas = $('#preview').cropper("getCroppedCanvas",size); // 生成 canvas 对象 var croppedCanvasUrl = croppedCanvas.toDataURL(originFileType); // Base64 ...}
なお、幅と高さの値を固定値に設定することは推奨されません。クロップ フレームのサイズは 100 100 (500 500 など) を超える場合がありますが、実際に生成される画像は 100 100 です。この結果、500 500 の高解像度画像が 100 100 の歪んだ画像に直接圧縮されます。同様に、クロップ ボックスが 100 100 より小さい場合、生成された画像はぼやけます。
文字列をバイナリに変換しますか? (フロントエンドは元々ページを作成するものでしたが、ファイル操作も行うようになりました。HTML5の登場以降、ブラウザもオペレーティングシステムとみなせるようになりました) 公式のDataURLtoBlobメソッドはないので、以下のように書くことしかできません。変換は非常に簡単です。ファイル タイプを逆アセンブルし、文字データを 16 進データに変換して配列に格納し、そのデータで Blob オブジェクトを初期化します。
function dataURLtoBlob(dataurl) { var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--){ u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], {type:mime});}function cropAndUpload(){ ... var croppedBlob = dataURLtoBlob(croppedCanvasUrl); croppedBlob.name = originFileName; // Blob对象没有name // Upload(croppedBlob);}
これで、この BLOB オブジェクトを FileObject のように処理できるようになりました。
実は、最新の HTML5 標準では HTMLCanvasElement.toBlob(callback, mimeType,quality) をサポートしています
croppedCanvas.toBlob(function(croppedBlob){ // Upload(croppedBlob);},originFileType)
MaxLeap チーム_UX メンバーの原著者: John Wang
元のリンク: https://blog.maxleap.cn/archives/705