2011-05-30 11 views
34

Tengo un elemento g que contiene uno o más elementos path. Como mencioné en another question, escalo y traduzco el elemento g al calcular un atributo transform para que encaje en una cuadrícula en otra parte del lienzo.¿Cómo se calcula el getBBox() SVGRect?

El cálculo se realiza utilizando la diferencia entre dos rectángulos, el getBBox() del elemento g y el rectángulo alrededor de la cuadrícula.

aquí está la pregunta - después de hacer la transformación, puedo actualizar el contenido del elemento g y llamo getBBox() de nuevo, sin la eliminación de la transform. El rectángulo resultante parece ser calculado sin considerar el transform. Hubiera esperado que reflejara el cambio. ¿Este comportamiento es consistente con la especificación SVG? ¿Cómo obtengo el cuadro delimitador del rectángulo transformado?

Esto, por cierto, está en un documento HTML 5 que se ejecuta en Firefox 4, si eso hace la diferencia.

Actualización: Aparentemente, este comportamiento parece muy claramente en violación de la especificación. A partir del texto here at w3c:

SVGRect getBBox()

Devuelve el cuadro de límite ajustado en el espacio de usuario actual (es decir, después de la aplicación del atributo 'transformar', si lo hay) de la geometría de todos elementos gráficos contenidos, exclusivos de caricias, recortes, enmascaramiento y efectos de filtro). Tenga en cuenta que getBBox debe devolver el cuadro delimitador real en el momento en que se llamó al método, incluso en el caso de que el elemento aún no se haya procesado.

¿Estoy leyendo esto correctamente? Si es así, parece ser una errata en la implementación de SVG que usa Firefox; No he tenido la oportunidad de probar ninguna otra. Me gustaría presentar un informe de error si alguien podría indicarme dónde.

+1

El soporte de SVG en los navegadores todavía es impredecible, después de 10 años. (Menos aún SMIL ... :() –

Respuesta

14

El comportamiento que se ve es correcta, y de conformidad con la especificación. Se aplica la transformación, luego la bbox se calcula en "unidades de usuario actuales", es decir, el espacio de usuario actual. Por lo tanto, si desea ver el resultado de una transformación en el elemento, deberá mirar la bbox de un nodo padre o similar. Es un poco confuso, pero se explica mucho mejor en el SVG Tiny 1.2 spec for SVGLocatable que contiene una serie de ejemplos que aclaran lo que se supone que debe hacer.

+2

Gracias por su respuesta - la especificación de SVG 1.1 es más que un poco confusa, al menos en este tema. – AlanObject

4

Parece que getBBox() no tiene en cuenta las transformaciones.

puedo señalar que aquí, por desgracia, no era capaz de hacer que trabaja: http://tech.groups.yahoo.com/group/svg-developers/message/22891

+1

Aparentemente esto parece estar en violación de la especificación - ver mi actualización anterior. – AlanObject

+0

Toma en cuenta la transformación, pero el elemento debe colocarse dentro de la etiqueta '' que se está transformando –

+0

solo funciona para ancho y alto, no da coordenada xy y. de todos modos agradable. Gracias. – atilkan

6

existen al menos 2 formas sencillas, pero un poco hacky que hacer lo que pide ... si hay maneras más agradables (menos hacky), no he encontrado todavía

FÁCIL HACKY # 1:
a) configure un rect que coincida con la bbox "no transformada" que group.getBBox() devuelve
b) aplique la "transformación no aplicada" del grupo a esa rect
c) rect.getBBox() ahora debe devolver el Bbox estás buscando

FÁCIL HACKY # 2: (sólo probado en cromo)
a) utilizar element.getBoundingClientRect(), que devuelve información suficiente para que usted pueda construir el Bbox se Están buscando

+0

getBoundingClientRect() funciona bien para que obtenga nueva información de tamaño sobre mis formas después de escalar. ¡Gracias! –

3

Los grupos de SVG tienen una práctica desagradable: no acumular todas las transformaciones realizadas. Tengo mi manera de lidiar con este problema. Estoy usando mis propios atributos para almacenar datos de transformación actuales que incluyo en cualquier transformación posterior. Use atributos compatibles con XML como alttext, value, name ... o simplemente xey para almacenar el valor acumulado como atributo.

Ejemplo:

<g id="group" x="20" y"="100" transform="translate(20, 100)"> 
<g id="subgroup" alttext="45" transform="rotate(45)"> 
<line...etc... 

Por lo tanto cuando estoy haciendo transformaciones estoy tomando los valores de los atributos mano, y al escribir de nuevo, estoy escribiendo tanto transformar y mismo valor con los atributos que hice solo por mantener todos los valores acumulados.

Ejemplo de rotación:

function symbRot(evt) { 

evt.target.ondblclick = function() { 

stopBlur(); 
var ptx=symbG.parentNode.lastChild.getAttribute("cx"); 
var pty=symbG.parentNode.lastChild.getAttribute("cy"); 
var currRot=symbG.getAttributeNS(null, "alttext"); 

var rotAng; 
if (currRot == 0) { rotAng = 90 } else if (currRot == 90) { rotAng = 180 } else if (currRot == 180) { rotAng = 270 } else if (currRot == 270) { rotAng = 0 }; 
symbG.setAttributeNS(null, "transform", "rotate(" + rotAng + "," + ptx + ", " + pty + ")"); 
symbG.setAttributeNS(null, "alttext", rotAng); 
}; 
} 
13

La gente a menudo se confunden con la diferencia de comportamiento de getBBox y getBoundingClientRect.

getBBox es un método nativo del elemento SVG como equivalente para encontrar el desplazamiento/ancho del cliente del elemento HTML DOM. El ancho y alto es que nunca va a cambiar incluso cuando se gira el elemento. No puede usarse para HTML DOM Elements.

getBoundingClientRect es común a los elementos HTML y SVG. El bounded rectangle ancho y alto cambiará cuando el elemento se gire o cuando se agrupen más elementos.

Cuestiones relacionadas