Com o JavaScript, posso alterar o índice / camada Z de um elemento SVG <g>?

86

Digamos que eu tenha algumas formas compostas ( <g>). Quero poder clicar e arrastá-los, mas quero que aquele que estou arrastando no momento fique em cima do outro na ordem Z, de modo que, se eu arrastá-lo sobre o OUTRO, o outro um deve ser eclipsado.

Corey Trager
fonte
veja aqui .
Eliran Malka
possível duplicata do Z-index de reordenamento
Eliran Malka

Respostas:

114

O índice Z em SVG é definido pela ordem em que os elementos aparecem no documento. Você terá que alterar a ordem dos elementos se quiser trazer uma forma específica para o topo.

Sam
fonte
1
@theonlygusti Os elementos no final do documento estão no topo. Se você estiver usando jQuery, deve ser capaz de usar algo como$('#thing-i-want-on-top').appendTo('#my-svg');
Adam Bradley
Então, basicamente, não há como fazer uma forma flutuar até o topo (eixo z) ao pairar ...?
chharvey
O jQuery não oferece suporte à alteração da ordem dos caminhos SVG.
Senthe
5
@chharvey, você pode levar as coisas para o topo reordenando-as - acrescentando novamente. Aqui está um exemplo elegante: codepen.io/osublake/pen/YXoEQe
Frazer Kirkman
36

Uma alternativa para mover elementos na árvore é usar <use>elementos onde você altera o xlink:hrefatributo para que ele forneça a ordem z que você deseja.

Aqui está um tópico antigo na lista de discussão svg-developers que discute este tópico no contexto de querer animar algumas formas.

Atualizar:

<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>

Neste exemplo, o elemento <use> é o último, o que o torna o primeiro elemento. Podemos escolher qualquer um dos outros elementos para atuar como frontais simplesmente alterando o xlink:hrefatributo. No exemplo acima, escolhemos o círculo com id="c1", o que o faz aparecer como o elemento superior.

Veja violino .

Erik Dahlström
fonte
1
Essa resposta seria muito mais útil com um exemplo ou com as informações dessa lista de e-mails (que é fechada).
Kyeotic
3
Funciona, mas faz você adicionar o uso apropriadamente. Se você usa traduções, <use> não tem ideia sobre elas
Jochen Bedersdorfer
@JochenBedersdorfer não tem certeza do que você quer dizer, como as traduções estão relacionadas ao ordenamento z?
Erik Dahlström
Não foi muito claro sobre isso. Se você usar <g> -tags aninhadas com transformações, precisará converter as coordenadas usando getTransformToElement (..); (ver documentos SVG)
Jochen Bedersdorfer
3
xlink:hrefestá obsoleto, agora é apenashref
osvein
22

Essa é uma velha questão, mas ...

No FireFox (7 ou superior) e no Chrome (14+), você pode colocar svg_element no topo. Isso não lhe dá liberdade de controle total do eixo z, mas é melhor do que nada;)

Basta anexar esse elemento novamente.

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

Achei que ia gerar um erro ou algo assim.

appendChild == substituir-se == redesenhar

CoR
fonte
3
Não é um erro de forma alguma; appendChildprimeiro remove do pai antigo, se houver, mesmo que seja o mesmo que o novo pai, depois o adiciona à lista de filhos do novo pai.
Potatoswatter
5

Outra solução não mencionada é colocar cada item svg / conjunto de itens em uma div. Você pode alterar o z-index dos divs facilmente.

Fiddle: ciclos de elementos SVG com z-index para contêineres

... Pressione os botões para 'empurrar' esse elemento para a frente. (vs. repintar todo o conjunto e empurrar 1 elemento para frente, mas mantendo a ordem original como na solução aceita)

Seria muito bom ter índices z relativos ...

stackOverflow quer que eu coloque o código se for um link de jsfiddle? ... ok

Roman Rekhler
fonte
5

Sim, a ordem é o que especifica qual objeto estará na frente do outro. Para manipular a ordem, você precisará mover coisas sobre o DOM. Há um bom exemplo disso no wiki SVG em https://www.w3.org/TR/SVG11/render.html#RenderingOrder

Kelly Anderson
fonte
4
Esse link não funciona mais. Este link explica a mesma ideia: link
Steve
4

Se você usar a biblioteca svg.js , poderá usar o comando ".front ()" para mover qualquer elemento para o topo.

Erel Segal-Halevi
fonte
3

SVGusa um "modelo de pintor" de renderização. A pintura é aplicada em operações sucessivas ao dispositivo de saída, de modo que cada operação pinte sobre alguma área do dispositivo de saída. Quando a área se sobrepõe uma área previamente pintada a nova pintura parcial ou completamente obscurece a old.- link para este

Ishank
fonte
3

Em SVG, para obter um índice Z maior e mais alto, você deve mover o elemento para baixo na árvore DOM. Você pode fazer isso com jQuery, selecionando o elemento SVG, removendo-o e anexando-o novamente na posição desejada:

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

O comentário de Adam Bradley à resposta de Sam foi exatamente direto. Ele usa jQuery em vez de apenas CSS, mas ele disse o seguinte:

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

No entanto, para o que eu estava criando, eu precisava que meu caminho SVG ficasse acima de qualquer outro caminho ao passar o mouse, mas ainda estivesse abaixo do meu texto SVG. Então aqui está o que eu inventei:

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

Ambos appendTo e insertBefore moverão seu elemento para um novo local, permitindo que você altere a profundidade do elemento SVG à vontade.

GRÁFICOS FiSH
fonte