Con JavaScript, ¿puedo cambiar el índice / capa Z de un elemento SVG <g>?

85

Digamos que tengo un par de formas compuestas ( <g>). Quiero poder hacer clic y arrastrarlos, pero quiero que el que estoy arrastrando en este momento esté encima del otro en el orden Z, de modo que si lo arrastro sobre el OTRO, el otro uno debería ser eclipsado.

Corey Trager
fuente
ver aquí .
Eliran Malka
posible duplicado del índice z de reordenamiento
Eliran Malka

Respuestas:

113

El índice Z en SVG se define por el orden en que aparecen los elementos en el documento. Tendrá que cambiar el orden de los elementos si desea llevar una forma específica a la parte superior.

Sam
fuente
1
@theonlygusti Los elementos al final del documento están en la parte superior. Si está usando jQuery, debería poder usar algo como$('#thing-i-want-on-top').appendTo('#my-svg');
Adam Bradley
Entonces, básicamente, ¿no hay forma de hacer flotar una forma hacia la parte superior (eje z) al pasar el mouse ...?
chharvey
jQuery no admite el cambio de orden de las rutas SVG.
Senthe
4
@chharvey, puede hacer flotar las cosas hacia la parte superior reordenándolas, volviendo a agregarlas. Aquí hay un ejemplo elegante: codepen.io/osublake/pen/YXoEQe
Frazer Kirkman
36

Una alternativa a mover elementos en el árbol es usar <use>elementos en los que cambie el xlink:hrefatributo para que le proporcione el orden z que desea.

Aquí hay un viejo hilo en la lista de correo de svg-developers que discute este tema en el contexto de querer animar algunas formas.

Actualizar:

<svg xmlns="http://www.w3.org/2000/svg" 
     xmlns:xlink="http://www.w3.org/1999/xlink"
     style="width:100%; height: 100%">
    <circle id="c1" cx="50" cy="50" r="40" fill="lime" />
    <rect id="r1" x="4" y="20" width="200" height="50" fill="cyan" />
    <circle id="c2" cx="70" cy="70" r="50" fill="fuchsia" />
    <use id="use" xlink:href="#c1" />
</svg>

En este ejemplo, el elemento <use> es el último, lo que lo convierte en el primer elemento. Podemos elegir cualquiera de los otros elementos para que actúen en primer plano simplemente cambiando el xlink:hrefatributo. En el ejemplo anterior, seleccionamos el círculo con id="c1", lo que hace que aparezca como el elemento superior.

Ver violín .

Erik Dahlström
fuente
1
Esta respuesta sería mucho más útil con un ejemplo o con la información de esa lista de correo (que está cerrada).
Kyeotic
3
Funciona, pero le hace agregar uso apropiadamente. Si usa traducciones, <use> no tiene idea sobre ellas
Jochen Bedersdorfer
@JochenBedersdorfer no estoy seguro de lo que quieres decir, ¿cómo se relacionan las traducciones con el orden z?
Erik Dahlström
No estaba muy claro sobre eso. Si usa etiquetas <g> anidadas con transformaciones, necesita convertir las coordenadas usando getTransformToElement (..); (ver documentos SVG)
Jochen Bedersdorfer
3
xlink:hrefestá en desuso, ahora es solohref
osvein
22

Esta es una vieja pregunta, pero ...

En FireFox (7+) y Chrome (14+), puede colocar svg_element en la parte superior. Esto no le da la libertad de control total del eje z, pero es mejor que nada;)

Simplemente agregue ese elemento nuevamente.

var svg = doc.createElemNS('svg');
var circle = doc.createElemNS('circle');
var line = doc.createElemNS('line');

svg.appendChild(circle); // appends it
svg.appendChild(line);   // appends it over circle
svg.appendChild(circle); // redraws it over line now

Pensé que iba a arrojar un error o algo así.

appendChild == reemplazarse a sí mismo == redibujar

CoR
fuente
3
No es un error en absoluto; appendChildprimero elimina del padre anterior, si lo hay, incluso si es el mismo que el nuevo padre, luego lo agrega a la lista de hijos del nuevo padre.
Potatoswatter
5

Otra solución que no se menciona es poner cada elemento svg / conjunto de elementos en un div. Puede modificar el índice Z de los divs fácilmente.

Fiddle: ciclos de elementos SVG con índice z para contenedores

... Presione los botones para 'empujar' ese elemento hacia el frente. (vs repintar todo el conjunto y empujar 1 elemento al frente, pero manteniendo el orden original como en la solución aceptada)

Sería muy bueno tener índices z relativos ...

stackOverflow quiere que ponga el código si es un enlace de jsfiddle? ... ook

Roman Rekhler
fuente
5

Sí, el orden es lo que especifica qué objeto estará frente al otro. Para manipular el orden, deberá mover cosas sobre el DOM. Hay un buen ejemplo de esto en la wiki de SVG en https://www.w3.org/TR/SVG11/render.html#RenderingOrder

Kelly Anderson
fuente
4
Ese enlace ya no funciona. Este enlace explica la misma idea: enlace
Steve
4

Si usa la biblioteca svg.js , puede usar el comando ".front ()" para mover cualquier elemento a la parte superior.

Erel Segal-Halevi
fuente
3

SVGutiliza un "modelo de pintores" de renderizado. La pintura se aplica en operaciones sucesivas al dispositivo de salida de manera que cada operación pinta sobre alguna área del dispositivo de salida. Cuando el área se superpone a un área previamente pintada, la pintura nueva oscurece parcial o completamente la anterior .

Ishank
fuente
3

En SVG, para obtener un índice Z más grande, debe mover el elemento hacia abajo en el árbol DOM. Puede hacer esto con jQuery, seleccionando el elemento SVG, eliminándolo y agregándolo nuevamente en la posición que desee:

$('g.element').remove().appendTo('svg');
Agu Dondo
fuente
2

El comentario de Adam Bradley a la respuesta de Sam fue exactamente acertado. Utiliza jQuery en lugar de solo CSS, pero dijo esto:

$('#thing-i-want-on-top').appendTo('#my-svg');

Sin embargo, para lo que estaba creando, necesitaba que mi ruta SVG estuviera por encima de cualquier otra ruta al pasar el mouse, pero aún debajo de mi texto SVG. Así que esto es lo que se me ocurrió:

$('#thing-i-want-on-top').insertBefore('#id-for-svg-text');

Tanto appendTo como insertBefore moverán su elemento a una nueva ubicación permitiéndole cambiar la profundidad del elemento SVG a voluntad.

GRÁFICOS FÍSICOS
fuente