61

Jcrop など、私が見つけた多くのライブラリは、実際にはトリミングを行わず、画像トリミング UI を作成するだけです。次に、実際のクロッピングを行うサーバーに依存します。

サーバー側のコードを使用せずにHTML5 機能を使用して、クライアント側で画像をトリミングするにはどうすればよいですか。

はいの場合、いくつかの例やヒントはありますか?

4

4 に答える 4

45

はい、できます。
これは、アンカー タグの新しい html5 "download" 属性に基づいています。
フローは次のようになります。

  1. 画像を読み込む
  2. トリミング境界を指定してキャンバスに画像を描画します
  3. キャンバスから画像データを取得hrefし、dom のアンカー タグの属性にします
  4. その要素に download 属性 ( download="desired-file-name") を追加します。aユーザーは「ダウンロード リンク」をクリックするだけで、画像が自分の PC にダウンロードされます。

機会があれば、デモで戻ってきます。

更新約束どおり、ライブ デモは
こちらです。jsfiddleロゴを取得し、各余白の 5 ピクセルをトリミングします。 コードは次のようになります。

var img = new Image();
img.onload = function(){
    var cropMarginWidth = 5,
        canvas = $('<canvas/>')
                    .attr({
                         width: img.width - 2 * cropMarginWidth,
                         height: img.height - 2 * cropMarginWidth
                     })
                    .hide()
                    .appendTo('body'),
        ctx = canvas.get(0).getContext('2d'),
        a = $('<a download="cropped-image" title="click to download the image" />'),
        cropCoords = {
            topLeft : {
                x : cropMarginWidth,
                y : cropMarginWidth 
            },
            bottomRight :{
                x : img.width - cropMarginWidth,
                y : img.height - cropMarginWidth
            }
        };

    ctx.drawImage(img, cropCoords.topLeft.x, cropCoords.topLeft.y, cropCoords.bottomRight.x, cropCoords.bottomRight.y, 0, 0, img.width, img.height);
    var base64ImageData = canvas.get(0).toDataURL();


    a
        .attr('href', base64ImageData)
        .text('cropped image')
        .appendTo('body');

    a
        .clone()
        .attr('href', img.src)
        .text('original image')
        .attr('download','original-image')
        .appendTo('body');

    canvas.remove();
}
img.src = 'some-image-src';

更新II
言及するのを忘れました:もちろん、マイナス
面があります:(。同じオリジンポリシーが画像にも適用されるため、(キャンバスメソッドを介して)画像のデータにアクセスしたい 場合toDataUrl
ドメインでホストされているかのようにイメージを提供するサーバー側プロキシ。

更新 III (セキュリティ上の理由から) これに関するライブ デモを提供することはできませんが、同一生成元ポリシーを解決する php サンプル コードを次に示します。

ファイル proxy.php:

$imgData = getimagesize($_GET['img']);
header("Content-type: " . $imgData['mime']);
echo file_get_contents($_GET['img']);  

このように、外部画像をその元から直接ロードする代わりに、次のようにします。

img.src = 'http://some-domain.com/imagefile.png';

プロキシ経由でロードできます:

img.src = 'proxy.php?img=' + encodeURIComponent('http://some-domain.com/imagefile.png');  

画像データ (base64) を実際の画像に保存するためのサンプル php コードを次に示します。

ファイルsave-image.php:

$data = preg_replace('/data:image\/(png|jpg|jpeg|gif|bmp);base64/','',$_POST['data']);
$data = base64_decode($data);
$img = imagecreatefromstring($data);

$path = 'path-to-saved-images/';
// generate random name
$name  = substr(md5(time()),10);
$ext = 'png';
$imageName = $path.$name.'.'.$ext;

// write the image to disk
imagepng($img,  $imageName);
imagedestroy($img);
// return the image path
echo $imageName;

その後、画像データをこのファイルにポストするだけで、画像がディスクに保存され、既存の画像ファイル名が返されます。

もちろん、これは少し複雑に感じるかもしれませんが、達成しようとしていることが可能であることを示したかったのです。

于 2012-10-04T14:52:35.007 に答える
7

Pixasticライブラリはまさにあなたが望むことを行います。ただし、キャンバスをサポートするブラウザーでのみ機能します。古いブラウザの場合は、次のいずれかを行う必要があります。

  1. サーバー側のフォールバックを提供する、または
  2. 大変申し訳ありませんが、最新のブラウザを入手する必要があることをユーザーに伝えてください。

もちろん、オプション #2 はあまりユーザーフレンドリーではありません。ただし、純粋なクライアントのみのツールを提供することを意図している場合、および/またはフォールバック バックエンド クロッパーをサポートできない場合 (たとえば、ブラウザー拡張機能またはオフライン Chrome アプリを作成している場合や、画像操作ライブラリを提供する適切なホスティング プロバイダー) の場合、ユーザー ベースを最新のブラウザーに限定するのが妥当でしょう。

編集: Pixastic を学びたくない場合は、jsFiddle hereに非常に単純なクロッパーを追加しました。この機能を変更して統合し、drawCroppedImageJcrop で使用できるようにする必要があります。

于 2012-10-04T14:41:05.233 に答える
3

#change-avatar-fileファイル入力 #change-avatar-fileは img タグ (jcrop のターゲット) 「キー」は FR.onloadend イベント https://developer.mozilla.org/en-US/docs/Web/API/FileReader

$('#change-avatar-file').change(function(){
        var currentImg;
        if ( this.files && this.files[0] ) {
            var FR= new FileReader();
            FR.onload = function(e) {
                $('#avatar-change-img').attr( "src", e.target.result );
                currentImg = e.target.result;
            };
            FR.readAsDataURL( this.files[0] );
            FR.onloadend = function(e){
                //console.log( $('#avatar-change-img').attr( "src"));
                var jcrop_api;

                $('#avatar-change-img').Jcrop({
                    bgFade:     true,
                    bgOpacity: .2,
                    setSelect: [ 60, 70, 540, 330 ]
                },function(){
                    jcrop_api = this;
                });
            }
        }
    });
于 2014-04-23T11:09:35.793 に答える
-1

それでも JCrop を使用する場合は、ファイルをトリミングするために必要なのは次の php 関数だけです。

$img_src = imagecreatefromjpeg($src);
$img_dest = imagecreatetruecolor($new_w,$new_h);
imagecopyresampled($img_dest,$img_src,0,0,$x,$y,$new_w,$new_h,$w,$h);
imagejpeg($img_dest,$dest);

クライアント側:

jQuery(function($){

    $('#target').Jcrop({
    onChange:   showCoords,
    onSelect:   showCoords,
    onRelease:  clearCoords
    });

});

var x,y,w,h; //these variables are necessary to crop
function showCoords(c)
{
    x = c.x;
    y = c.y;
    w = c.w;
    h = c.h;
};
function clearCoords()
{
    x=y=w=h=0;
}
于 2012-10-04T15:04:13.263 に答える