2012-05-01 8 views
19

Básicamente estoy haciendo esta pregunta JavaScript: Calculate Bounding box coordinates from a rotated rectangleCalcular X del cuadro delimitador, Y, altura y anchura de un elemento girado a través de JavaScript

Diagram

En este caso:

  • iX = Ancho del elemento HTML girado (azul)
  • iY = Altura del elemento HTML girado (azul)
  • bx = Ancho de Boundin g Box (rojo)
  • por = Altura del cuadro delimitador (rojo)
  • x = X coord de cuadro delimitador (rojo)
  • y = Y coord de cuadro delimitador (rojo)
  • iAngle/t = Ángulo de rotación del elemento HTML (azul; que no se muestra, pero utiliza en código de abajo), su información: Es 37 grados en este ejemplo (no es que importe para el ejemplo)

¿Cómo se calculan las coordenadas X, Y, altura y anchura 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 para esto será obtener los coordenada X/Y girados del elemento HTML (cuadro azul) para usar de alguna manera como un desplazamiento (esto no se representa en el código siguiente). Esto bien puede tener que mirar CSS3's transform-origin para determinar el punto central.

Tengo una solución parcial, pero el cálculo de las coordenadas X/Y no está funcionando 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) 
    } 
}; 

me siento como si estuviera tan cerca, y tan lejos ...

Muchas gracias por cualquier ayuda que pueda proporcionar!

para ayudar al NO JAVASCRIPTERS ...

Una vez que el elemento HTML se gira, el navegador devuelve una "transformación de matriz" o "matriz de rotación", que parece ser la siguiente: rotate(Xdeg) = matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0);See this page for more info.

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

Nueva Información

Humm ... interesante ...

enter image description here

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

También debe tenerse en cuenta que $(document).ready(function() {...}); dispara demasiado pronto para que se reconozca el X/Y girado (¡lo cual fue parte de mi problema original!). Estoy rotando los elementos directamente antes de las llamadas de interrogación X/Y en $(document).ready(function() {...});, pero no parecen actualizarse hasta algún tiempo después de (!?).

Cuando tenga un poco más de tiempo, voy a lanzar un jFiddle con el ejemplo, pero estoy usando una forma modificada de "jquery-css-transform.js", así que tengo un poco de retoque antes de la jFiddle ...

Entonces ... ¿qué pasa, FireFox? Eso no es genial, hombre!

La trama se complica ...

Bueno, parece FF12 para solucionar el problema con FF11, y ahora actúa como IE y Opera. Pero ahora estoy de vuelta a la casilla uno con X/Y, pero al menos creo que sé por qué ahora ...

Parece que a pesar de que los navegadores informan correctamente el X/Y para el objeto girado , todavía existe un "fantasma" X/Y en la versión sin rotación. Parece como si este es el orden de las operaciones:

  • A partir de un elemento de un-girada en una X, Y de 20,20
  • girar dicho elemento, lo que resulta en la presentación de X, Y como 15 , 35
  • Mover dicho elemento a través de JavaScript/CSS a X, Y 10,10
  • El navegador vuelve a girar lógicamente el elemento a 20,20, se mueve a 10,10 y luego lo vuelve a girar, lo que da como resultado una X, Y de 5,25

Así que ... Quiero que el elemento termine en 10,10 post rotatorio ión, pero gracias al hecho de que el elemento es (aparentemente) girado post moviendo, el resultante X, Y difiere del conjunto X, Y.

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

+1

Se puede publicar un diagrama de lo que quiere? Las imágenes hablan mil palabras y todo. –

+0

Puse una segunda foto, especialmente para que * usted * pueda ver lo que está haciendo. –

+0

¡Gracias! El diagrama realmente era necesario (en lugar de confiar en la imagen de Q referida). – Campbeln

Respuesta

1

Convierta las cuatro esquinas en vectores desde el centro, gírelas y obtenga el nuevo ancho/alto min/max de ellas.

EDIT:

veo donde está teniendo problemas ahora. Está haciendo los cálculos utilizando todo el lado cuando necesita hacerlo con los desplazamientos desde el centro de rotación. Sí, esto da como resultado cuatro puntos rotados (que, curiosamente, es exactamente tantos puntos como comenzó). Entre ellos habrá un mínimo X, un máximo X, un mínimo Y y un máximo Y. Esos son tus límites.

+0

Gracias, pero soy muy matemático-estúpido (nunca me gustó y rara vez me gustó =) Estoy seguro de que estás en lo cierto, pero necesito que lo sostengas de la mano. – Campbeln

+1

No se puede ir girando sin tropezar con algunos trigonometría. ;) 'SOH CAH TOA! SOH CAH TOA! SOH ... 'Es mucho más fácil aprender una vez que lo necesitas para resolver un problema real que te importa, en lugar de problemas de clase que no tienen importancia. (* "El granjero Jones tiene un asta de bandera de altura 5 y el sol está en un ángulo de 36 grados ... ¿cuánto tiempo dura la sombra?" *) –

5

¿Ha intentado utilizar getBoundingClientRect()?

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

+2

Esa función no es consciente de la transformación en la mayoría de los navegadores. Consulte https://developer.mozilla.org/en-US/docs/DOM/element.getBoundingClientRect – Hoffmann

13

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

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

espero que alguien lo encuentra útil!

En realidad, no estoy calculando su x, y para la esquina superior izquierda del contenedor. Se calcula como resultado de la desviación (código del ejemplo 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); 

Saludos

+0

¡Qué asombroso es esto! Justo lo que estaba buscando: D – docodemore

+0

hola, muy bien, ¿cómo lo adaptarías para manejar una forma que no gira alrededor de su centro? – winthers

+0

Para completar, este cálculo funciona si tiene un ángulo entre 0 y 2 * PI, ** Y ** aplicando esta corrección (del violín): 'this.angulo = ((rotador.angulo> Math.PI * 0.5 && rotador.angulo Math.PI * 1.5 && rotador.angulo rixo

Cuestiones relacionadas