基本上我是在问JavaScript这个问题:Calculate Bounding box coordinates from a rotated rectangle
在这种情况下:
如何通过JavaScript计算旋转的HTML元素(给定其宽度,高度和旋转角度)周围的边界框(所有红色数字)的X,Y,高度和宽度?一个棘手的问题是将旋转的HTML元素(蓝色框)的原始X / Y坐标用作某种方式的偏移(这在下面的代码中没有表示)。这可能需要查看CSS3's transform-origin以确定中心点。
我有一个部分解决方案,但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)
}
};
我觉得自己如此接近,但到目前为止......
非常感谢您提供的任何帮助!
帮助非JAVASCRIPTERS ......
旋转HTML元素后,浏览器会返回“矩阵变换”或“旋转矩阵”,如下所示:rotate(Xdeg) = matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0);
See this page for more info。
我有一种感觉,这将启发我们如何仅根据旋转元素的宽度,高度和角度(蓝色)获取边界框(红色)的X,Y。
新信息
嗯......很有意思......
每个浏览器似乎都以不同于X / Y的角度处理旋转! FF完全忽略它,IE&amp; Opera绘制边界框(但其属性未公开,即:bx&amp; by)和Chrome&amp; Safari旋转矩形!除FF外,所有都正确报告X / Y.所以......只有FF存在X / Y问题!多奇怪啊!
另外值得注意的是,$(document).ready(function () {...});
似乎太早触发旋转的X / Y(这是我原来问题的一部分!)。我在$(document).ready(function () {...});
中的X / Y询问调用之前直接旋转元素,但它们似乎直到(!?)之后的某个时间才更新。
当我多花一点时间的时候,我会用这个例子折腾jFiddle,但我正在使用“jquery-css-transform.js”的修改形式,所以我在jFiddle之前做了一点点的修修补补...
那么......什么事,FireFox?那不酷,伙计!
情节变浓......
好吧,FF12似乎解决了FF11的问题,现在就像IE和Opera一样。但是现在我回到了X / Y的方方面面,但至少我想我知道为什么现在......
似乎即使浏览器正确报告旋转对象的X / Y,在未旋转的版本上仍然存在“重影”X / Y.似乎这是操作的顺序:
所以...我希望元素在旋转后的10,10处结束,但是由于元素(看似)在移动后重新旋转,因此得到的X,Y与集合X不同,收率
这是我的问题!因此我真正需要的是获取所需目标坐标(10,10)的功能,并从那里向后工作以获得将导致元素旋转到10,10的起始X,Y坐标。至少我知道我现在的问题是什么,感谢浏览器的内部工作原理,似乎旋转元素10 = 5!
答案 0 :(得分:14)
我知道这有点晚了,但我在HTML5画布上为这个问题编写了一个小提琴:
http://jsfiddle.net/oscarpalacious/ZdQKg/
我希望有人觉得它很有用!
我实际上并没有计算容器左上角的x,y。它是作为偏移的结果计算的(来自小提琴示例的代码):
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);
干杯
答案 1 :(得分:5)
您是否尝试过使用 getBoundingClientRect()?
此方法返回一个对象,当前值“bottom,height,left,right,top,width”考虑旋转
答案 2 :(得分:1)
将四个角从中心转为矢量,旋转它们,并从中获取新的最小/最大宽度/高度。
修改强>
我现在看到你遇到问题的地方。当您需要使用旋转中心的偏移量进行计算时,您正在使用整个侧面进行计算。是的,这导致四个旋转点(奇怪的是,这与你开始时的点数完全相同)。在他们之间将有一个最小X,一个最大X,一个最小Y和一个最大Y.这些是你的界限。
答案 3 :(得分:0)
My gist可以帮助您
多边形的边界框(矩形,三角形等):
现场演示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);
});
椭圆的边框:
现场演示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);