Flashなしで画像の切り抜きを実現——HTML 5中級レベル

6959 ワード

前言
画像の切り抜きアップロードは、ユーザーの体験にぴったり合う機能だけでなく、特定の画像サイズを統一し、ウェブサイトのレイアウトを最適化し、一石二鳥にすることができます.
需要はそんなに簡単で、ブラウザで画像を切り取ってサーバーにアップロードします.
私が最初に考えた方法は、画像とトリミングパラメータ(x,y,scale,rotate)をサーバ、サーバにアップロードして画像処理を行い、so easyです.しかし、これは潮流の発展の方向に合わない:先端でできる処理は、先端に置いてやりましょう.流れと妥協した結果、先端はますます複雑になった.
最初はブラウザが画像を読み取り、生成できるとは思わなかった.考えてみてください.「クリック・コピー」という簡単な機能を作るには、Flashのブラウザを借りる必要があります.権限がそんなに大きいわけではありません.
各种のウェブサイトを参照して、画像をローカルに処理する限り、基本的にFlashを借りました.適当に写して、APIがなくて、たとえ画像を修正することができても、アップロードパスはどのように変更するか分かりません.もっと重要なのは、Flashについて全然知らないことです.
幸い、私たちのウェブサイトはすでにIE 9以下のブラウザを完全に捨てて、現代のHTML 5ブラウザにしか対応していません.(OperaもマイクロソフトもWebkitカーネルのルートを歩き始めましたが、Chromeについて行くのが潮流です)希望とHTML 5しか送れないので、工夫してみると、次のような流れが可能であることがわかりました.
Created with Raphal 2.1.0元のピクチャFileオブジェクト初期化CropperピクチャBase 64プレビューCropper裁断パラメータに基づいてCanvas(Base 64)Base 64を描画Blobオブジェクトを回転して裁断されたBlobオブジェクトをアップロードする
以下では、各セクションについて詳しく説明します.
元の画像ファイルオブジェクトを取得
各ピクチャファイル処理の開始は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
ここではとても使いやすいライブラリcropperを紹介します.js https://github.com/fengyuanchen/cropperマスクを生成したり、トリミングパラメータを取得したり、canvasを出力したり...しかも絶対軽量級で、圧縮後のcssとjsコードは30 KBしかありません.彼はJQueryに基づいているので、JQueryを導入するのはもっと大きいかもしれません.しかし、今どのサイトがJQueryを使っていませんか?IE 9+と互換性があり、移動端の体験が良好で、タッチスケールに応答し、ドラッグすることができます.以下はアンドロイド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);  //         
}

Canvasの描画
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
    ...
}

なお、widthおよびheightの値は、固定値として設定することは推奨されない.トリミングボックスのサイズは100*100(例えば500*500)を超える可能性がありますが、実際に生成された画像は100*100で、このような結果は500*500のハイビジョン画像を直接100*100の歪み画像に圧縮することです.同様に、トリミングボックスが100*100未満では、生成された画像がぼやけます.
Base 64回転Blobオブジェクト
文字列をバイナリに変換しますか?(フロントエンドはもともとページを作っていたので、今でもファイルを操作し始めました.HTML 5があればブラウザをオペレーティングシステムとして使えるようになりました)公式にはDataURLtoBlobの方法はありませんので、自分で1つ書くしかありません.変換も簡単です.ファイルタイプを分解し、文字データを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);
}

FileObjectのようにこのblobオブジェクトを処理できるようになりました.
実は最新のHTML 5規格ではHTMLCanvasElement.toBlob(callback, mimeType, quality)に対応しています
croppedCanvas.toBlob(function(croppedBlob){
    // Upload(croppedBlob);
},originFileType)

曲がりくねったが、やはり勉強になった.
原文の著者はMaxLeapチームから来ました.UXメンバー:John王