2012-08-30 22 views
5

Estoy tratando de encontrar la mejor manera de obtener el cuadro delimitador de un elemento SVG arbitrario en los píxeles de la pantalla, con el fin de superponer un elemento HTML correctamente. Mi enfoque hasta ahora ha sido usar .getBBox() y .getCTM() para recuperar el cuadro delimitador del objeto y la matriz de transformación, luego aplicar la transformación a los puntos del cuadro delimitador como se describe en la respuesta aceptada al this question.Obtener los límites de un elemento SVG girado en píxeles de pantalla?

// get the element 
var el = $(selector)[0], 
    pt = $(selector).closest('svg')[0].createSVGPoint(); 

// get the bounding box and matrix 
var bbox = el.getBBox(), 
    matrix = el.getScreenCTM(); 

pt.x = bbox.x; 
pt.y = bbox.y; 
var nw = pt.matrixTransform(matrix); 
pt.x += bbox.width; 
pt.y += bbox.height; 
var se = pt.matrixTransform(matrix); 

// make a div in the screen space around the object 
var $div = $('<div class="bbox"/>').css({ 
     left: nw.x, 
     top: nw.y, 
     width: se.x - nw.x, 
     height: se.y - nw.y 
    }) 
    .appendTo('body'); 

Se puede ver mi prueba aquí: http://jsfiddle.net/nrabinowitz/zr2jX/

Sin embargo, como muestra de prueba, este enfoque parece fallar cuando hay una rotación incluido en la transformación - se ve como el cuadro de límite se calcula pre- rotación, por lo que no funciona las esquinas del cuadro delimitador girado.

¿Cómo puedo calcular correctamente el cuadro delimitador no girado de los elementos transformados?

Respuesta

4

Después de algunas investigaciones, aquí están las mejores opciones que he encontrado:

  • getBoundingClientRect() parece funcionar bien para los elementos SVG en los navegadores modernos, y es bastante rápido, pero los resultados pueden variar un poco de plataforma para plataforma (especialmente si tiene un ancho de carrera considerable). Sin embargo, para el punto de @Sergiu, esto no tiene en cuenta los cambios en la forma, y ​​le da los límites del cuadro delimitador girado, no la ruta u objeto real, por lo que puede ser bastante impreciso: see criticism here. Ejemplo violín: http://jsfiddle.net/stevenbenner/6M5zf/

  • Mi principal objetivo era conseguir esquinas de posición y puntos medios del rectángulo delimitador, y al final he decidido que el uso de la caja de contorno girado incluso podría ser preferible a la caja delimitadora "real" de un girada forma. Pude hacer esto usando el enfoque anterior, y luego ciclando los puntos para acercarme lo más posible a las posiciones N, S, E, W. Se puede ver mi ejemplo violín aquí: http://jsfiddle.net/nrabinowitz/sPtzV/

3

No creo que sea posible, porque la inclinación y la rotación implican un cambio de perfil , o la apariencia de las proyecciones de la forma en los dos ejes.

Puede calcular la matriz de transformación que ignoraría la parte de rotación de la CTM, pero entonces no tiene ninguna garantía de que la nueva BBox todavía rodeará su elemento girado. Por ejemplo, si tiene un círculo, la rotación no afecta las dimensiones del cuadro delimitador. Si, por otro lado, tienes un diamante como la ruta base, y lo giras 45 grados, de modo que al final solo es un cuadrado, el cuadro delimitador es diferente: originalmente estabas midiendo la diagonal, y ahora tienes que obtener un cuadro delimitador que mide la longitud del lado. No importa cómo use el CTM, no puede tener en cuenta el cambio de forma.

Por lo tanto, la rotación es bastante importante, ignorando que no es una opción; pero solo el cuadro delimitador local y la matriz de transformación no dicen nada acerca de cómo cambia el perfil de forma cuando se rota.

+0

Ese es un buen punto, pero a) que sería mejor si pudiera conseguir los límites básicos de la caja de contorno girado, y b) espero que hay algo que No sé en la API SVG que puede darme un nuevo cuadro delimitador basado en la forma transformada. – nrabinowitz

+0

En teoría, podría usar [checkEnclosure] (http://www.w3.org/TR/SVG11/struct.html#__svg__SVGSVGElement__checkEnclosure) para realizar una especie de búsqueda binaria para el rectángulo más pequeño que encierra completamente su elemento.Desafortunadamente [aún no está implementado en Firefox] (https://bugzilla.mozilla.org/show_bug.cgi?id=501421). –

Cuestiones relacionadas