2016-09-09 4 views
0

レンダリングエンジンを作成しようとしていますが、計算にはいくつかの問題があります。問題は、この画像がキャンバスの制限内にあるかどうかを検出するために、画像の描画された境界ボックスを取得したいということです。キャンバスで回転するイメージの境界ボックスを取得する

私は位置、ピボット位置(必ずしも画像の中心にない)と回転を持っているので、それは複雑になります。私は検索しましたが、これは非常に便利な機能ですが、この特定の問題について話す投稿は見つかりませんでした。それは働いていない https://jsfiddle.net/feo196nm/

function getBoundaryDraw(x, y, pivotX, pivotY, width, height, rotationRadian) { 
    // getting the width and height 
    var realWidth = Math.abs(Math.cos(rotationRadian)) * width + Math.abs(Math.sin(rotationRadian)) * height; 
    var realHeight = Math.abs(Math.cos(rotationRadian)) * height + Math.abs(Math.sin(rotationRadian)) * width; 

    // trying to get the position in canvas 
    // I dont know what I'm doing **insert mad scientist dog here** 
    var dx = pivotX - width/2; 
    var dy = pivotY - height/2; 
    var h = Math.sqrt(dx*dx+dy*dy); 
    var da = rotationRadian + Math.asin(dx/h); 
    var x = x + pivotX + width/2 - realWidth/2 - h * Math.cos(da); 
    var y = y + pivotY + height/2 - realHeight/2 - h * Math.sin(da); 

    // log result to have some debug 
    console.log(dx, dy, h, da, x, y); 

    // return random numbers 
    return { 
    x: x, 
    y: y, 
    width: realWidth, 
    height: realHeight 
    }; 
} 

...私はほとんどすべての組み合わせを使用:

はここで、これまで私の仕事です。助けてください。 ありがとうございました

答えて

0

ここはコードの回答です。 x軸とy軸の回転軸を計算し、それらを使用してコーナーの位置を計算し、次にすべてのコーナーの最小値と最大値を求めてその範囲を取得します。

これは、負のスケールとゼロスケールを含めて独立してスケールされた画像では機能します。イメージの原点は、イメージの内側または外側にあることができますが、エクステントには含まれません。

デモでは、縮尺、ボトム軸とその境界ボックス(範囲)、すべての画像の境界ボックスの原点が設定された回転画像がいくつか表示されます。

これが役に立ちます。

var canvas = document.createElement("canvas"); 
 
canvas.width = 800; 
 
canvas.height = 400; 
 
var ctx = canvas.getContext("2d"); 
 
document.body.appendChild(canvas); 
 

 
var image = new Image(); 
 
image.src = "https://i.stack.imgur.com/C7qq2.png?s=328&g=1"; 
 

 
// get the extent of an Image object with its 
 
// origin at x,y (local origin cx,cy) scaled sx, sy 
 
// and rotated ang. 
 
// returns extent object. 
 
// if you supply an extent will add to it if it is valid 
 
function getImageBounds(img, x, y, cx, cy, sx, sy, ang, extent) { 
 
    var xdx = Math.cos(ang) * sx; // x axis 
 
    var xdy = Math.sin(ang) * sx; 
 

 
    var ydx = -Math.sin(ang) * sy; // y axis 
 
    var ydy = Math.cos(ang) * sy; 
 

 
    if (extent === null || extent === undefined) { // create extent if does not exist 
 
     extent = { 
 
      top : Infinity, 
 
      left : Infinity, 
 
      right : -Infinity, 
 
      bottom : -Infinity, 
 
     }; 
 
    } 
 
    var r = img.width - cx; // right coord 
 
    var b = img.height - cy; // bottom 
 
    var p = [// the 4 corner points [x,y,x,y... 
 
     -cx * xdx + (-cy * ydx) + x, 
 
     -cx * xdy + (-cy * ydy) + y, 
 
     r * xdx + (-cy * ydx) + x, 
 
     r * xdy + (-cy * ydy) + y, 
 
     r * xdx + b * ydx + x, 
 
     r * xdy + b * ydy + y, 
 
     - cx * xdx + b * ydx + x, 
 
     - cx * xdy + b * ydy + y, 
 
    ]; 
 
    extent.left = Math.min(extent.left, p[0], p[2], p[4], p[6]); 
 
    extent.top = Math.min(extent.top, p[1], p[3], p[5], p[7]); 
 
    extent.right = Math.max(extent.right, p[0], p[2], p[4], p[6]); 
 
    extent.bottom = Math.max(extent.bottom, p[1], p[3], p[5], p[7]); 
 
    extent.width = extent.right - extent.left; 
 
    extent.height = extent.bottom - extent.top; 
 
    return extent; 
 
} 
 
function drawImage(img) { // draws image 
 
    ctx.setTransform(1, 0, 0, 1, img.x, img.y) 
 

 
    ctx.rotate(img.ang); 
 
    ctx.scale(img.sx, img.sy); 
 

 
    ctx.drawImage(image, -img.cx, -img.cy); 
 
} 
 

 
function createImg() { // image object factory 
 
    return { 
 
     x : 0, 
 
     y : 0, 
 
     cx : 0, 
 
     cy : 0, 
 
     sx : 1, 
 
     sy : 1, 
 
     ang : 0, 
 
    }; 
 
} 
 

 
var imgs = [createImg(), createImg(), createImg(), createImg(), createImg(), createImg(), createImg(), createImg()]; 
 
ctx.lineWidth = 2; 
 

 
// primes 467, 479, 487, 491, 499,859, 863, 877, 881, 883, 
 
function update(time) { 
 
    ctx.fillStyle = "#888"; 
 
    ctx.fillRect(0, 0, 800, 400); 
 
    if (image.complete) { 
 
     time = time * 0.08; 
 
     for (var i = 0; i < imgs.length; i += 1) { // move images properties semi random 
 
      var g = imgs[i]; 
 
      var t1 = time/(467 + i * 877); 
 
      var t2 = time/(863 + i * 499); 
 
      g.x = Math.cos(t1) * 300 + 400; 
 
      g.y = Math.sin(t2) * 150 + 200; 
 
      t1 *= 5; 
 
      t2 *= 5; 
 
      g.sx = Math.cos(t1) * 0.32 * Math.cos(t2); 
 
      g.sy = Math.sin(t2) * 0.32 * Math.cos(t1); 
 
      t1 *= 5; 
 
      t2 *= 5; 
 
      g.cx = Math.cos(t1) * image.width * 0.5 + image.width * 0.5; 
 
      g.cy = Math.sin(t2) * image.height * 0.5 + image.height * 0.5; 
 
      g.ang += Math.sin(t2/6) * 0.1; 
 
      t1 *= 5; 
 
      t2 *= 5; 
 
     } 
 
     var extentAll = null; // to get extent all 
 
     for (var i = 0; i < imgs.length; i += 1) { // draw image and get extent and show extent 
 
      var g = imgs[i]; 
 
      drawImage(g); 
 
      extentAll = getImageBounds(image, g.x, g.y, g.cx, g.cy, g.sx, g.sy, g.ang, extentAll); 
 
      var extent = getImageBounds(image, g.x, g.y, g.cx, g.cy, g.sx, g.sy, g.ang); 
 
      ctx.setTransform(1, 0, 0, 1, 0, 0); /// reset the transform 
 
      ctx.strokeStyle = "red"; 
 
      ctx.strokeRect(extent.left, extent.top, extent.width, extent.height); 
 
      ctx.fillStyle = "#FA0"; 
 
      ctx.fillRect(g.x - 5, g.y - 5, 10, 10); 
 

 
     } 
 
     ctx.strokeStyle = "blue"; 
 
     ctx.strokeRect(extentAll.left, extentAll.top, extentAll.width, extentAll.height); 
 

 
    } else { 
 
     ctx.font = "32px arial"; 
 
     ctx.textAlign = "center"; 
 
     ctx.textBaseline = "middle"; 
 
     ctx.fillText("Loading...", 400, 200); 
 
    } 
 

 
    // do it all again 
 

 
    requestAnimationFrame(update); 
 

 
} 
 
requestAnimationFrame(update);

関連する問題