简体   繁体   English

通过JavaScript计算旋转元素的边界框的X,Y,高度和宽度

[英]Calculate the bounding box's X, Y, Height and Width of a rotated element via JavaScript

Basically I'm asking this question for JavaScript: Calculate Bounding box coordinates from a rotated rectangle 基本上我是在问JavaScript这个问题: 从旋转的矩形计算边界框坐标

图

In this case: 在这种情况下:

  • iX = Width of rotated (blue) HTML element iX =旋转(蓝色)HTML元素的宽度
  • iY = Height of rotated (blue) HTML element iY =旋转(蓝色)HTML元素的高度
  • bx = Width of Bounding Box (red) bx =边界框宽度(红色)
  • by = Height of Bounding Box (red) by =边界框高度(红色)
  • x = X coord of Bounding Box (red) x =边界框的X坐标(红色)
  • y = Y coord of Bounding Box (red) y =边界框的Y坐标(红色)
  • iAngle/t = Angle of rotation of HTML element (blue; not shown but used in code below), FYI: It's 37 degrees in this example (not that it matters for the example) iAngle / t = HTML元素的旋转角度(蓝色;未显示但在下面的代码中使用),仅供参考:在此示例中它是37度(不是对于示例而言重要)

How does one calculate the X, Y, Height and Width of a bounding box (all the red numbers) surrounding a rotated HTML element (given its width, height, and Angle of rotation) via JavaScript? 如何通过JavaScript计算旋转的HTML元素(给定其宽度,高度和旋转角度)周围的边界框(所有红色数字)的X,Y,高度和宽度? A sticky bit to this will be getting the rotated HTML element (blue box)'s original X/Y coords to use as an offset somehow (this is not represented in the code below). 一个棘手的问题是将旋转的HTML元素(蓝色框)的原始X / Y坐标用作某种方式的偏移(这在下面的代码中没有表示)。 This may well have to look at CSS3's transform-origin to determine the center point. 这可能需要查看CSS3的变换原点来确定中心点。

I've got a partial solution, but the calculation of the X/Y coords is not functioning properly... 我有一个部分解决方案,但X / Y坐标的计算不正常...

var boundingBox = function (iX, iY, iAngle) {
    var x, y, bx, by, t;

    //# Allow for negetive iAngle's that rotate counter clockwise while always ensuring iAngle's < 360
    t = ((iAngle < 0 ? 360 - iAngle : iAngle) % 360);

    //# Calculate the width (bx) and height (by) of the .boundingBox
    //#     NOTE: See https://stackoverflow.com/questions/3231176/how-to-get-size-of-a-rotated-rectangle
    bx = (iX * Math.sin(iAngle) + iY * Math.cos(iAngle));
    by = (iX * Math.cos(iAngle) + iY * Math.sin(iAngle));

    //# This part is wrong, as it's re-calculating the iX/iY of the rotated element (blue)
    //# we want the x/y of the bounding box (red)
    //#     NOTE: See https://stackoverflow.com/questions/9971230/calculate-rotated-rectangle-size-from-known-bounding-box-coordinates
    x = (1 / (Math.pow(Math.cos(t), 2) - Math.pow(Math.sin(t), 2))) * (bx * Math.cos(t) - by * Math.sin(t));
    y = (1 / (Math.pow(Math.cos(t), 2) - Math.pow(Math.sin(t), 2))) * (-bx * Math.sin(t) + by * Math.cos(t));

    //# Return an object to the caller representing the x/y and width/height of the calculated .boundingBox
    return {
        x: parseInt(x), width: parseInt(bx),
        y: parseInt(y), height: parseInt(by)
    }
};

I feel like I am so close, and yet so far... 我觉得自己如此接近,但到目前为止......

Many thanks for any help you can provide! 非常感谢您提供的任何帮助!

TO HELP THE NON-JAVASCRIPTERS... 帮助非JAVASCRIPTERS ...

Once the HTML element is rotated, the browser returns a "matrix transform" or "rotation matrix" which seems to be this: rotate(Xdeg) = matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0); 旋转HTML元素后,浏览器返回“矩阵变换”或“旋转矩阵”,它似乎是这样的: rotate(Xdeg) = matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0); See this page for more info . 有关详细信息,请参阅此页面

I have a feeling this will enlighten us on how to get the X,Y of the bounding box (red) based solely on the Width, Height and Angle of the rotated element (blue). 我有一种感觉,这将启发我们如何仅根据旋转元素的宽度,高度和角度(蓝色)获得边界框(红色)的X,Y。

New Info 新信息

Humm... interesting... 嗯...有趣......

在此输入图像描述

Each browser seems to handle the rotation differently from an X/Y perspective! 每个浏览器似乎都以不同于X / Y的角度处理旋转! FF ignores it completely, IE & Opera draw the bounding box (but its properties are not exposed, ie: bx & by) and Chrome & Safari rotate the rectangle! FF完全忽略它,IE和Opera绘制边界框(但它的属性没有暴露,即:bx&by)并且Chrome和Safari旋转矩形! All are properly reporting the X/Y except FF. 除FF外,所有都正确报告X / Y. So... the X/Y issue seems to exist for FF only! 所以......只有FF存在X / Y问题! How very odd! 多奇怪啊!

Also of note, it seems that $(document).ready(function () {...}); 另外值得注意的是,似乎$(document).ready(function () {...}); fires too early for the rotated X/Y to be recognized (which was part of my original problem!). 对于旋转的X / Y进行识别太早了(这是我原来问题的一部分!)。 I am rotating the elements directly before the X/Y interrogation calls in $(document).ready(function () {...}); 我在$(document).ready(function () {...});的X / Y询问调用之前直接旋转元素$(document).ready(function () {...}); but they don't seem to update until some time after(!?). 但它们似乎直到(!?)之后的某个时间才更新。

When I get a little more time, I will toss up a jFiddle with the example, but I'm using a modified form of "jquery-css-transform.js" so I have a tiny bit of tinkering before the jFiddle... 当我得到更多的时间时,我会用一个例子来折腾jFiddle,但我使用的是“jquery-css-transform.js”的修改形式,所以我在jFiddle之前做了一点点的修补......

So... what's up, FireFox? 那么......什么事,FireFox? That ain't cool, man! 那不酷,伙计!

The Plot Thickens... 情节变厚......

Well, FF12 seems to fix the issue with FF11, and now acts like IE and Opera. 好吧,FF12似乎解决了FF11的问题,现在就像IE和Opera一样。 But now I am back to square one with the X/Y, but at least I think I know why now... 但现在我回到X / Y的方方面面,但至少我想我知道为什么现在......

It seems that even though the X/Y is being reported correctly by the browsers for the rotated object, a "ghost" X/Y still exists on the un-rotated version. 似乎即使浏览器正确地报告旋转对象的X / Y,在未旋转的版本上仍然存在“重影”X / Y. It seems as though this is the order of operations: 似乎这是操作的顺序:

  • Starting with an un-rotated element at an X,Y of 20,20 从未旋转的元素开始,X,Y为20,20
  • Rotate said element, resulting in the reporting of X,Y as 15,35 旋转所述元素,导致X,Y报告为15,35
  • Move said element via JavaScript/CSS to X,Y 10,10 将所述元素通过JavaScript / CSS移动到X,Y 10,10
  • Browser logically un-rotates element back to 20,20, moves to 10,10 then re-rotates, resulting in an X,Y of 5,25 浏览器逻辑上将元素旋转回20,20,移动到10,10然后重新旋转,得到X,Y为5,25

So... I want the element to end up at 10,10 post rotation, but thanks to the fact that the element is (seemingly) re-rotated post move, the resulting X,Y differs from the set X,Y. 所以...我希望元素在旋转后的10,10处结束,但是由于元素(看似)在移动后重新旋转,因此得到的X,Y与集合X,Y不同。

This is my problem! 这是我的问题! So what I really need is a function to take the desired destination coords (10,10), and work backwards from there to get the starting X,Y coords that will result in the element being rotated into 10,10. 因此我真正需要的是获取所需目标坐标(10,10)的功能,并从那里向后工作以获得将导致元素旋转到10,10的起始X,Y坐标。 At least I know what my problem is now, as thanks to the inner workings of the browsers, it seems with a rotated element 10=5! 至少我知道我现在的问题是什么,感谢浏览器的内部工作原理,似乎旋转元素10 = 5!

I know this is a bit late, but I've written a fiddle for exactly this problem, on an HTML5 canvas: 我知道这有点晚了,但我在HTML5画布上为这个问题编写了一个小提琴:

http://jsfiddle.net/oscarpalacious/ZdQKg/ http://jsfiddle.net/oscarpalacious/ZdQKg/

I hope somebody finds it useful! 我希望有人觉得它很有用!

I'm actually not calculating your x,y for the upper left corner of the container. 我实际上并没有计算容器左上角的x,y。 It's calculated as a result of the offset (code from the fiddle example): 它是作为偏移的结果计算的(来自小提琴示例的代码):

this.w = Math.sin(this.angulo) * rotador.h + Math.cos(this.angulo) * rotador.w;
this.h = Math.sin(this.angulo) * rotador.w + Math.cos(this.angulo) * rotador.h;
// The offset on a canvas for the upper left corner (x, y) is
// given by the first two parameters for the rect() method:
contexto.rect(-(this.w/2), -(this.h/2), this.w, this.h);

Cheers 干杯

Have you tried using getBoundingClientRect() ? 你尝试过使用getBoundingClientRect()吗?

This method returns an object with current values of "bottom, height, left, right, top, width" considering rotations 考虑到旋转此方法返回具有“底部,高度,左,右,顶部,宽度”的当前值的对象

Turn the four corners into vectors from the center, rotate them, and get the new min/max width/height from them. 将四个角从中心转换为矢量,旋转它们,并从中获取新的最小/最大宽度/高度。

EDIT: 编辑:

I see where you're having problems now. 我现在看到你遇到问题的地方。 You're doing the calculations using the entire side when you need to be doing them with the offsets from the center of rotation . 当您需要使用旋转中心的偏移量进行计算时,您正在使用整个侧面进行计算。 Yes, this results in four rotated points (which, strangely enough, is exactly as many points as you started with). 是的,这导致了四个旋转点(奇怪的是,这与你开始时的点数完全相同)。 Between them there will be one minimum X, one maximum X, one minimum Y, and one maximum Y. Those are your bounds. 在它们之间将有一个最小X,一个最大X,一个最小Y和一个最大Y.这些是你的界限。

My gist can help you 我的要点可以帮到你

Bounding box of a polygon (rectangle, triangle, etc.): 多边形的边界框(矩形,三角形等):

Live demo https://jsfiddle.net/Kolosovsky/tdqv6pk2/ 现场演示https://jsfiddle.net/Kolosovsky/tdqv6pk2/

let points = [
    { x: 125, y: 50 },
    { x: 250, y: 65 },
    { x: 300, y: 125 },
    { x: 175, y: 175 },
    { x: 100, y: 125 },
];
let minX = Math.min(...points.map(point => point.x));
let minY = Math.min(...points.map(point => point.y));
let maxX = Math.max(...points.map(point => point.x));
let maxY = Math.max(...points.map(point => point.y));
let pivot = {
    x: maxX - ((maxX - minX) / 2),
    y: maxY - ((maxY - minY) / 2)
};
let degrees = 90;
let radians = degrees * (Math.PI / 180);
let cos = Math.cos(radians);
let sin = Math.sin(radians);

function rotatePoint(pivot, point, cos, sin) {
    return {
        x: (cos * (point.x - pivot.x)) - (sin * (point.y - pivot.y)) + pivot.x,
        y: (sin * (point.x - pivot.x)) + (cos * (point.y - pivot.y)) + pivot.y
    };
}

let boundingBox = {
    x1: Number.POSITIVE_INFINITY,
    y1: Number.POSITIVE_INFINITY,
    x2: Number.NEGATIVE_INFINITY,
    y2: Number.NEGATIVE_INFINITY,
};

points.forEach((point) => {
    let rotatedPoint = rotatePoint(pivot, point, cos, sin);

    boundingBox.x1 = Math.min(boundingBox.x1, rotatedPoint.x);
    boundingBox.y1 = Math.min(boundingBox.y1, rotatedPoint.y);
    boundingBox.x2 = Math.max(boundingBox.x2, rotatedPoint.x);
    boundingBox.y2 = Math.max(boundingBox.y2, rotatedPoint.y);
});

Bounding box of an ellipse: 椭圆的边界框:

Live demo https://jsfiddle.net/Kolosovsky/sLc7ynd1/ 现场演示https://jsfiddle.net/Kolosovsky/sLc7ynd1/

let centerX = 350;
let centerY = 100;
let radiusX = 100;
let radiusY = 50;
let degrees = 200;

let radians = degrees * (Math.PI / 180);
let radians90 = radians + Math.PI / 2;
let ux = radiusX * Math.cos(radians);
let uy = radiusX * Math.sin(radians);
let vx = radiusY * Math.cos(radians90);
let vy = radiusY * Math.sin(radians90);

let width = Math.sqrt(ux * ux + vx * vx) * 2;
let height = Math.sqrt(uy * uy + vy * vy) * 2;
let x = centerX - (width / 2);
let y = centerY - (height / 2);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从给定的坐标(x,y)计算边界框的宽度和高度 - Calculate bounding box width and height from given coordinates(x,y) 访问内联 SVG 转换后的组边界框(x 和 y 位置、宽度和高度)? - Access inline SVG's transformed group bounding box (x and y position, width and height)? 根据x和y坐标以及javascript中的宽度和高度值计算面积 - calculate an area based on x and y coordinates and width and height values in javascript 从x,y,宽度,高度和旋转角度获取旋转的矩形点 - Get rotated rectangle points from x, y, width, height and rotation 调整旋转元素的大小时计算正确的宽度和高度 - Calculate correct width and height when resizing a rotated element 如何在JavaScript中计算旋转3D立方体的x和y坐标? - How to calculate x and y coordinates of a rotated 3D cube in JavaScript? 如何测量Javascript上旋转元素的宽度和高度? - How can I measure the width and height of a rotated element on Javascript? 如何计算围绕其角旋转的矩形的边界框? - How to calculate a bounding box for a rectangle rotated around its corner? 旋转时如何获取元素的高度和宽度 - How to get height and width of element when it is rotated 在 JavaScript canvas 中显示多个图像特定的 X、Y、宽度和高度 - Show multiple images specific X, Y, width and height in JavaScript canvas
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM