variable tutorial error div calculate javascript css geometry rotation bounding-box

tutorial - undefined javascript error



Calcule la X, Y, altura y anchura del cuadro delimitador de un elemento girado a través de JavaScript (4)

¿Has intentado usar getBoundingClientRect () ?

Este método devuelve un objeto con valores actuales de "abajo, altura, izquierda, derecha, arriba, ancho" considerando rotaciones

Básicamente, estoy haciendo esta pregunta por JavaScript: Calcular las coordenadas del cuadro delimitador de un rectángulo girado

En este caso:

  • iX = Ancho del elemento HTML girado (azul)
  • iY = Altura del elemento HTML girado (azul)
  • bx = Ancho del cuadro delimitador (rojo)
  • por = Altura de la caja delimitadora (rojo)
  • x = X coord de la caja delimitadora (rojo)
  • y = coordenada Y del cuadro delimitador (rojo)
  • iAngle / t = ángulo de rotación del elemento HTML (azul; no se muestra pero se usa en el código a continuación), FYI: En este ejemplo, es 37 grados (no es que importe para el ejemplo)

¿Cómo se calcula una X, Y, Altura y Ancho de un cuadro delimitador (todos los números rojos) que rodean un elemento HTML girado (dado su ancho, alto y Ángulo de rotación) a través de JavaScript? Un poco pegajoso a esto será conseguir que los acordes X / Y originales del elemento HTML girado (caja azul) se utilicen como compensación de alguna manera (esto no está representado en el código a continuación). Esto puede tener que ver el origen de transformación de CSS3 para determinar el punto central.

Tengo una solución parcial, pero el cálculo de los acordes X / Y no funciona correctamente ...

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) } };

Siento que estoy tan cerca, y sin embargo tan lejos ...

Muchas gracias por cualquier ayuda que pueda proporcionar!

PARA AYUDAR A LOS NO JAVASCRIPTERS ...

Una vez que se gira el elemento HTML, el navegador devuelve una "transformada de matriz" o "matriz de rotación" que parece ser esto: rotate(Xdeg) = matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0); Vea esta página para más información .

Tengo la sensación de que esto nos iluminará sobre cómo obtener la X, Y del cuadro delimitador (rojo) basándose únicamente en el ancho, la altura y el ángulo del elemento girado (azul).

Nueva informacion

Humm ... interesante ...

¡Cada navegador parece manejar la rotación de manera diferente desde una perspectiva X / Y! FF lo ignora por completo, IE y Opera dibujan el cuadro delimitador (pero sus propiedades no están expuestas, es decir, bx & by) y Chrome y Safari giran el rectángulo. Todos están reportando correctamente el X / Y excepto FF. Entonces ... ¡el problema de X / Y parece existir solo para FF! ¡Qué extraño!

También de la nota, parece que $(document).ready(function () {...}); se dispara demasiado pronto para que se reconozca el X / Y rotado (¡que era parte de mi problema original!). Estoy rotando los elementos directamente antes de las llamadas de interrogación X / Y en $(document).ready(function () {...}); pero parece que no se actualizan hasta algún tiempo después de (!?).

Cuando tenga un poco más de tiempo, lanzaré un jFiddle con el ejemplo, pero estoy usando una forma modificada de "jquery-css-transform.js", por lo que tengo un poco de retoques antes del jFiddle ...

Entonces ... ¿qué pasa, FireFox? Eso no está bien, hombre!

La trama se complica...

Bueno, FF12 parece solucionar el problema con FF11, y ahora actúa como IE y Opera. Pero ahora he vuelto al punto uno con el X / Y, pero al menos creo que sé por qué ahora ...

Parece que a pesar de que el X / Y está siendo informado correctamente por los navegadores para el objeto girado, todavía existe un X / Y "fantasma" en la versión sin girar. Parece que este es el orden de las operaciones:

  • Comenzando con un elemento sin girar en una X, Y de 20,20
  • Gire dicho elemento, lo que resulta en el informe de X, Y como 15,35
  • Mueve dicho elemento a través de JavaScript / CSS a X, Y 10,10
  • El navegador lógicamente des-gira el elemento de nuevo a 20,20, se mueve a 10,10 y luego gira nuevamente, resultando en una X, Y de 5,25

Así que ... quiero que el elemento termine en 10,10 post rotación, pero debido al hecho de que el elemento es (aparentemente) girado después del movimiento, el X, Y resultante difiere del conjunto X, Y.

¡Este es mi problema! Entonces, lo que realmente necesito es una función para tomar los acordes de destino deseados (10,10), y trabajar hacia atrás desde allí para obtener los acordes de X, Y iniciales que resultarán en la rotación del elemento en 10,10. ¡Al menos ahora sé cuál es mi problema, ya que, gracias al funcionamiento interno de los navegadores, parece que con un elemento girado 10 = 5!


Convierta las cuatro esquinas en vectores desde el centro, gírelas y obtenga de ellas el nuevo ancho / alto mínimo / máximo.

EDITAR:

Veo donde estás teniendo problemas ahora. Está haciendo los cálculos utilizando todo el lado cuando necesita hacerlo con las compensaciones desde el centro de rotación . Sí, esto da como resultado cuatro puntos rotados (que, por extraño que parezca, son exactamente tantos puntos como empezaste). Entre ellos habrá un mínimo de X, un máximo de X, un mínimo de Y y un máximo de Y. Esos son sus límites.


Sé que es un poco tarde, pero he escrito un violín para exactamente este problema, en un lienzo HTML5:

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

Espero que alguien lo encuentre útil!

En realidad no estoy calculando tu x, y para la esquina superior izquierda del contenedor. Se calcula como resultado del desplazamiento (código del ejemplo de violín):

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);

Aclamaciones


Mi esencia puede ayudarte

Cuadro delimitador de un polígono (rectángulo, triángulo, etc.):

Demostración en vivo 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); });

Caja delimitadora de una elipse:

Demostración en vivo 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);