2016-10-16 2 views
-1

もう少し大きなキャンバスのビューポートとして、より小さなキャンバスを使用しようとしています。 私は実際に同様の質問の解決策thisで使用されているアプローチが好きです。大きな画像からhtml5キャンバスのビューポート

彼は基本的にCanvasRenderingContext2D.drawImage()を使用してバッファ/オフセットキャンバスを「トリミング」し、画像のその部分を小さなキャンバス(ビューポート)に表示します。私はこのフィドルで指定されたソリューションのより単純なバージョンを実装しようとしています:https://jsfiddle.net/avvac0x8/2/。しかし、あなたが見ることができるように、ビューポートは大きな画像と完全に同期していません(またその逆もあります)。

上記の解決策は、さまざまなキャンバスサイズでは機能しないようです。ですから、私はそれを「キャンバスサイズにとらわれない」ものにする必要があります。

多分、私はスケーリング計算のいくつかの種類が不足しているかもしれませんが、私はここから行く方法を知らない、任意のヒントは歓迎です。

EDIT:https://jsfiddle.net/avvac0x8/4/

を正常に動作させるにはフィドルを更新しました。元々元の画像をバッファキャンバスに合わせて縮尺すべきではありません。その代わりに、オフセット/バッファキャンバスは元のイメージと同じサイズにする必要があります。

答えて

0

最も簡単な方法は、別のキャンバスを中間層として使用することです。

ここでは、オフセットキャンバスは無視されます。これは、マップ全体を表示する必要がないためではありません。恐らくあなたが必要とするのはズームインされた領域だけです。ズームアウトしたい場合は、幅と高さのパラメータをctx.drawImage (img, x, y, viewPort.width, viewPort.height)に設定して、ビューポートウィンドウに画像全体を描画するだけです。ただし、画像が伸びて表示されないように、画像が適切なサイズに手動で切り取られていることを確認するか、キャンバスビューポートが使用している画像と同じアスペクト比であることを確認してください。

背景のクリッピング領域(実際の表示領域)を、ビューポートウィンドウ(拡大/縮小表示領域)とは異なるサイズ(小さいまたは大きい)にしたい場合は、以下のように動作します。これは、実際の背景がどれくらい大きいか小さいかには依存しないことに注意してください。おそらく、切り取られた領域とビューポートウィンドウの両方が、背景画像自体よりも小さい。例えば

// use these to determine where the clipping region lives 
var offsetX = 0, 
    offsetY = 0, 
    clipWidth = <<yourChosenPixelWidth>>, 
    clipHeight = <<yourChosenPixelHeight>>, 
    clip = document.createElement ("canvas"), 
    clipCtx, 
    viewPort = document.getElementById ("main-canvas"), 
    viewCtx = viewPort.getContext ("2d"), 
    background = new Image(), 
    // offsetCanvas = document.getElementById ("offset-canvas"), 
    imgLoaded = false; 

// configure the offset canvas once 
background.src = "http://pixeljoint.com/files/icons/full/map__r1470206141.png"; 
background.onLoad = function() { 
    // the fiddle scales the image, here we don't 
    //offsetCanvas.width = background.width; 
    //offsetCanvas.height = background.height; 
    //offsetCtx = offsetCanvas.getContext ("2d"); 
    //offsetCtx.drawImage (background, 0, 0); 
    imgLoaded = true; 
} 

clip.width = clipWidth; 
clip.height = clipHeight; 
clipCtx = clip.getContext ("2d"); 

function updateViewport() { 
    if (imgLoaded) { 
     // copy pixels from the background directly 
     // to the middle layer so we have a "clipped" 
     // but unscaled image object 
     //clipCtx.putImageData (offsetCtx.getImageData (offsetX, offsetY, clip.width, clip.height)); 
     clipCtx.drawImage (background, offsetX, offsetY); 

     // this is where rescaling happens 
     viewCtx.drawImage (clip, 0, 0, viewPort.width, viewPort.height); 

     // and you're done! 
    } 
} 
+0

私は多分あなたはフィドルの上に手の込んだことができ、私は非常にあなたの説明を理解しないと思いますか? 私は以下の前提を使用しています: - 現在のビューポートの位置を実際に表示するにはバッファ付きのキャンバスが必要です(正確にあなたの呼び出し側の "中間層"です) - 元のイメージをキャンバスサイズに拡大縮小する必要がありません。私が実際に必要とするのは、元の画像と同じ幅/高さのキャンバスを持つことです。 概念の証明として提案したように私のフィドルを更新するほうがいいかもしれませんか? –

+0

私はこの答えが十分明確だとは思わないが。本当の問題が何であるかを大まかに知っているので、私はそれを受け入れたものとしてチェックするつもりです。私は質問を編集したので、解決策の実際の例が含まれています。大きな感謝! –

+0

@TMG遅く返事を申し訳ありません。お役に立てて嬉しいです。 :-)私が指摘したいことの1つは、特定の理由でオフセットキャンバスが必要な場合を除いて、イメージオブジェクト自体が有効な幅と高さのプロパティを持ち、メインのキャンバスに直接描画できることです。どちらの方法でも同じように動作します。 – Nolo

関連する問題