我正在尝试制作渲染引擎,但我的计算有些困难。问题是我想获取图像的绘制边界框以检测此图像是否在画布限制内。
但它变得复杂,因为我有一个位置,一个枢轴位置(并不总是以图像为中心)和一个旋转。我搜索过,但没有找到任何关于这个问题的帖子,虽然这是一个非常有用的功能。
到目前为止,这是我的工作: 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 :(得分:0)
以下是代码中的答案。计算x和y旋转的缩放轴,然后使用它们计算角落位置,然后找到所有角落的最小值和最大值以获得范围。
它适用于独立缩放的图像,包括负标度和零标度。图像原点可以在图像内部或外部,但不包括在范围内。
该演示显示了几个旋转的图像,其中包括刻度,原点设置为bothe轴及其边界框(范围)和所有图像的边界框。
希望这有帮助。
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);