Вопрос по javascript, css – Вычислить X, Y, Высота и Ширина ограничивающего прямоугольника повернутого элемента с помощью JavaScript

21

По сути, я задаю этот вопрос для JavaScript:Рассчитать координаты ограничительной рамки из повернутого прямоугольника

Diagram

В этом случае:

iX = Width of rotated (blue) HTML element iY = Height of rotated (blue) HTML element bx = Width of Bounding Box (red) by = Height of Bounding Box (red) x = X coord of Bounding Box (red) y = Y coord of Bounding Box (red) 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)

Как рассчитать X, Y, высоту и ширину ограничивающего прямоугольника (все красные цифры), окружающего повернутый элемент HTML (с учетом его ширины, высоты и угла поворота) с помощью JavaScript? Важным моментом для этого будет получение повернутых 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)
    }
};

Я чувствую, что я так близко, и все же так далеко ...

Большое спасибо за любую помощь, вы можете предоставить!

TO HELP THE NON-JAVASCRIPTERS...

После поворота HTML-элемента браузер возвращает «матричное преобразование». или «матрица вращения»; что, кажется, это:rotate(Xdeg) = matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0); Смотрите эту страницу для получения дополнительной информации.

У меня есть ощущение, что это поможет нам понять, как получить X, Y ограничивающего прямоугольника (красного цвета), основываясь исключительно на ширине, высоте и угле повернутого элемента (синего цвета).

New Info

Хм ... интересно ...

enter image description here

Кажется, что каждый браузер обрабатывает вращение по-разному с точки зрения X / Y! FF игнорирует это полностью, IE & amp; Opera рисует ограничивающий прямоугольник (но его свойства не выставляются, т.е. bx & amp; by) и Chrome & amp; Сафари вращать прямоугольник! Все правильно сообщают о X / Y, кроме FF. Итак ... кажется, что проблема X / Y существует только для FF! Как странно!

Также примечательно, кажется, что$(document).ready(function () {...}); слишком рано, чтобы распознать повернутый X / Y (что было частью моей первоначальной проблемы!). Я вращаю элементы непосредственно перед вызовом X / Y$(document).ready(function () {...}); но они, кажется, не обновляются до некоторого времени после (!?).

Когда у меня будет немного больше времени, я добавлю jFiddle с примером, но я использую измененную форму «jquery-css-transform.js». так что у меня есть немного возиться перед jFiddle ...

Итак ... что случилось, FireFox? Это не круто, чувак!

The Plot Thickens...

Что ж, FF12, похоже, решает проблему с FF11, и теперь действует как IE и Opera. Но теперь я вернулся к исходной точке с X / Y, но, по крайней мере, я думаю, что знаю, почему сейчас ...

Кажется, что хотя X / Y правильно сообщает браузерами для повернутого объекта, «ghost» X / Y все еще существует в не повернутой версии. Кажется, что это порядок операций:

Starting with an un-rotated element at an X,Y of 20,20 Rotate said element, resulting in the reporting of X,Y as 15,35 Move said element via JavaScript/CSS to 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

Итак ... Я хочу, чтобы элемент заканчивался на 10,10 после поворота, но благодаря тому факту, что элемент (казалось бы) переворачивается после перемещения, результирующие X, Y отличаются от набора X, Y.

Это моя проблема! Итак, что мне действительно нужно, так это функция, которая берет желаемые координаты назначения (10,10) и работает оттуда назад, чтобы получить начальные координаты X, Y, которые приведут к повороту элемента в 10,10. По крайней мере, я знаю, в чем моя проблема сейчас, так как благодаря внутренней работе браузеров, кажется, с повернутым элементом 10 = 5!

Вы должны опубликовать & quot; до & quot; картинка для вашей выгоды. Ignacio Vazquez-Abrams
Я вторую картину, особенно для того, чтобыyou может видеть, что вы делаете. Ignacio Vazquez-Abrams
Спасибо! Диаграмма действительно была необходима (вместо того, чтобы полагаться на ссылочную картинку Q). Campbeln
Можете ли вы опубликовать схему того, что вы хотите? Картины говорят тысячу слов и все. Li-aung Yip
Моя цель - начать с "после". & Quot; до & quot; будет синяя коробка без поворота. А благодаря свойству CSS3 transform-origin синее поле можно поворачивать из любой центральной точки. Увидеть:w3schools.com/cssref/css3_pr_transform-origin.asp ... конечно, если это делает вопрос невозможным, тогда я буду переоценивать =) Campbeln

Ваш Ответ

4   ответа
5

getBoundingClientRect() ?

Этот метод возвращает объект с текущими значениями"bottom, height, left, right, top, width" учитывая повороты

Error: User Rate Limit Exceededdeveloper.mozilla.org/en-US/docs/DOM/…
1

поверните их и получите от них новую минимальную / максимальную ширину / высоту.

EDIT:

Я вижу, где у вас сейчас проблемы. Вы выполняете вычисления, используя всю сторону, когда вам нужно их выполнятьwith the offsets from the center of rotation, Да, это приводит кfour повернутые точки (что, как ни странно, ровно столько же точек, сколько вы начали). Между ними будет один минимум X, один максимум X, один минимум Y и один максимум Y. Это ваши границы.

Error: User Rate Limit ExceededSOH CAH TOA! SOH CAH TOA! SOH...Error: User Rate Limit Exceeded"Farmer Jones has a flagpole of height 5 and the sun is at an angle of 36 degrees... how long is the shadow?")
Error: User Rate Limit Exceeded Campbeln
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);

ура

Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededANDError: User Rate Limit Exceededthis.angulo = ((rotador.angulo > Math.PI * 0.5 && rotador.angulo < Math.PI * 1) || (rotador.angulo > Math.PI * 1.5 && rotador.angulo < Math.PI * 2))? Math.PI - rotador.angulo : rotador.angulo;
Error: User Rate Limit Exceeded
0

Мой суть могу помочь тебе

Bounding box of a polygon (rectangle, triangle, etc.):

Live демо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 демо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);

Похожие вопросы