web-dev-qa-db-ja.com

キャンバスに収まるように画像を拡大縮小する

ユーザーが画像をアップロードできるフォームがあります。

イメージがロードされると、サーバーに戻す前にファイルサイズを縮小するためにいくつかのスケーリングを実行します。

これを行うには、キャンバスに配置し、そこで操作します。

このコードは、サイズ320 x 240pxのキャンバスを使用して、キャンバス上にスケーリングされたイメージをレンダリングします。

ctx.drawImage(img, 0, 0, canvas.width, canvas.height)

...ここで、canvas.widthとcanvas.heightは、画像の高さと幅x元の画像のサイズに基づくスケーリング係数です。

しかし、コードを使用する場合:

ctx.drawImage(img, 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height

...キャンバス上の画像の一部、この場合は左上隅のみを取得します。実際の画像サイズは320x240のキャンバスサイズよりも大きいにもかかわらず、キャンバスに収まるように画像全体を「拡大縮小」する必要があります。

したがって、上記のコードの場合、幅と高さは1142x856であり、これが最終的な画像サイズです。フォームが送信されたときにサーバーにベックを渡すためにそのサイズを維持する必要がありますが、ユーザーのキャンバスに表示されるのは小さいビューのみです。

ここで何が欠けていますか?誰かが私を正しい方向に向けることができますか?

事前に感謝します。

65
dradd

最初の長方形としてソース画像(img)サイズを提供します:

ctx.drawImage(img, 0, 0, img.width,    img.height,     // source rectangle
                   0, 0, canvas.width, canvas.height); // destination rectangle

2番目の長方形は、宛先サイズ(ソース長方形のスケーリング先)です。

2016年6月6日更新:アスペクト比とポジショニング(ala CSSの「カバー」メソッド)については、チェックアウト:
シミュレーション背景サイズ:キャンバスのカバー

100
user1693593

2番目の呼び出しで、ソースのサイズをターゲットのサイズに設定するためにエラーを作成しました。
とにかく、スケーリングされた画像に同じアスペクト比が欲しいと思うので、それを計算する必要があります:

var hRatio = canvas.width / img.width    ;
var vRatio = canvas.height / img.height  ;
var ratio  = Math.min ( hRatio, vRatio );
ctx.drawImage(img, 0,0, img.width, img.height, 0,0,img.width*ratio, img.height*ratio);

また、画像を中央に配置したいので、コードは次のようになります。

function drawImageScaled(img, ctx) {
   var canvas = ctx.canvas ;
   var hRatio = canvas.width  / img.width    ;
   var vRatio =  canvas.height / img.height  ;
   var ratio  = Math.min ( hRatio, vRatio );
   var centerShift_x = ( canvas.width - img.width*ratio ) / 2;
   var centerShift_y = ( canvas.height - img.height*ratio ) / 2;  
   ctx.clearRect(0,0,canvas.width, canvas.height);
   ctx.drawImage(img, 0,0, img.width, img.height,
                      centerShift_x,centerShift_y,img.width*ratio, img.height*ratio);  
}

あなたはここのjsbinでそれを見ることができます: http://jsbin.com/funewofu/1/edit?js,output

117
GameAlchemist