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


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é en la parte superior del otro en el orden Z, de modo que si lo arrastro sobre el OTRO, el otro uno debe ser eclipsado.


75
2018-01-27 02:11


origen


Respuestas:


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


102
2018-01-27 02:27



Una alternativa a mover elementos en el árbol es usar <use> elementos donde cambias el xlink:href atributo para que te dé el orden z que deseas.

Aquí hay un viejo hilo en svg-developers lista de correo sobre 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 elemento más adelantado. Podemos elegir cualquiera de los otros elementos para actuar como fachada simplemente cambiando el xlink:href atributo. En el ejemplo anterior elegimos el círculo con id="c1", lo que lo hace aparecer como el elemento superior.

Ver violín.


25
2018-06-09 08:03



Esta es una vieja pregunta, pero ...

En FireFox (7+) y Chrome (14+) puedes sacar svg_element a la cima. Esto no le da libertad de control del eje Z completo, pero es mejor que nada;)

Solo agrega ese elemento de nuevo.

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 == volver a dibujar


21
2017-11-07 23:46



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

Fiddle: elementos SVG ciclos con z-index para contenedores

... Presione los botones para 'empujar' ese elemento hacia el frente. (frente a 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 coloque el código si es un enlace de jsfiddle? ... ook

var orderArray=[0,1,2];
var divArray = document.querySelectorAll('.shape');
var buttonArray = document.querySelectorAll('.button');

for(var i=0;i<buttonArray.length;i++){
    buttonArray[i].onclick=function(){
        var localI = i;
        return function(){clickHandler(orderArray.indexOf(localI));};
    }();
}


function clickHandler(divIndex) {
     orderArray.push(orderArray.splice(divIndex, 1)[0]);
    orderDivs();
}

function orderDivs(){
    for(var i=0;i<orderArray.length;i++){
       divArray[orderArray[i]].style.zIndex=i;        
    }
}
svg {
    width: 100%;
    height: 100%;
    stroke: black;
    stroke-width:2px;
    pointer-events: all;
}
div{
    position:absolute;
}
div.button{
    top:55%;
    height:5%;
    width:15%;
    border-style: outset;
    cursor:pointer;
    text-align: center;
    background:rgb(175, 175, 234);
    
}
div.button:hover{
    border-style: inset;
    background:yellow;
    
}
div.button.first{
    left:0%;
}
div.button.second{
    left:20%;
}
div.button.third{
    left:40%;
}
<div class="shape">
    <svg>
    <circle cx="50" cy="50" r="40" fill="lime" />
    </svg>
</div>
<div class="shape">
    <svg>
        <rect x="4" y="20" width="200" height="50" fill="cyan" />
    </svg>
</div>
<div class="shape">
    <svg>
        <circle cx="70" cy="70" r="50" fill="fuchsia" />
    </svg>
</div>

<div class='button first'>lime</div>
<div class='button second'>cyan</div>
<div class='button third'>fuchsia</div>


4
2018-03-06 17:49



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


4
2018-03-13 12:15



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


4
2018-01-27 02:49



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


3
2018-01-16 13:03



El comentario de Adam Bradley a la respuesta de Sam fue exactamente el punto. Usa jQuery en lugar de CSS solamente, pero dijo esto:

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

Sin embargo, para lo que estaba creando, necesitaba mi ruta SVG para estar por encima de cualquier otra ruta en el vuelo estacionario, pero aún estar 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 que le permitirá cambiar la profundidad del elemento SVG a voluntad.


0
2017-08-26 11:54



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 añadiéndolo nuevamente en la posición que desee:

$('g.element').remove().appendTo('svg');

0
2017-10-04 21:00