Avec JavaScript, puis-je changer l'index / la couche Z d'un élément SVG <g>?

85

Disons que j'ai quelques formes composites ( <g>). Je veux pouvoir les cliquer et les faire glisser, mais je veux que celui que je traîne en ce moment soit au-dessus de l'autre dans l'ordre Z, de sorte que si je le fais glisser sur l'AUTRE, l'autre on devrait être éclipsé.

Corey Trager
la source
voir ici .
Eliran Malka
duplication possible de la réorganisation SVG z-index (Raphael facultatif)
Eliran Malka

Réponses:

113

L'index Z en SVG est défini par l'ordre d'apparition des éléments dans le document. Vous devrez changer l'ordre des éléments si vous souhaitez amener une forme spécifique vers le haut.

Sam
la source
1
@theonlygusti Les éléments à la fin du document sont en haut. Si vous utilisez jQuery, vous devriez pouvoir utiliser quelque chose comme$('#thing-i-want-on-top').appendTo('#my-svg');
Adam Bradley
Donc, fondamentalement, il n'y a aucun moyen de faire flotter une forme vers le haut (axe z) en survol…?
chharvey
jQuery ne prend pas en charge le changement de l'ordre des chemins SVG.
Senthe le
4
@chharvey, vous pouvez faire flotter les choses vers le haut en les réorganisant - en les rajoutant. Voici un exemple élégant: codepen.io/osublake/pen/YXoEQe
Frazer Kirkman
36

Une alternative au déplacement d'éléments dans l'arborescence consiste à utiliser des <use>éléments dans lesquels vous modifiez l' xlink:hrefattribut afin qu'il vous donne l'ordre z souhaité.

Voici un ancien fil de discussion sur la liste de diffusion svg-développeurs traitant de ce sujet dans le contexte de la volonté d'animer certaines formes.

Mise à jour:

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

Dans cet exemple, l'élément <use> est le dernier, ce qui en fait l'élément le plus en avant. Nous pouvons choisir n'importe lequel des autres éléments pour agir en premier en changeant simplement l' xlink:hrefattribut. Dans l'exemple ci-dessus, nous avons choisi le cercle avec id="c1", ce qui le fait apparaître comme l'élément le plus haut.

Voir violon .

Erik Dahlström
la source
1
Cette réponse serait beaucoup plus utile avec un exemple, ou avec les informations de cette liste de diffusion (qui est fermée).
Kyeotic
3
Fonctionne, mais vous permet d'ajouter une utilisation appropriée. Si vous utilisez des traductions, <use> n'en a aucune idée
Jochen Bedersdorfer
@JochenBedersdorfer ne sais pas ce que vous voulez dire, comment les traductions sont-elles liées à l'ordre de z?
Erik Dahlström
N'était pas très clair à ce sujet. Si vous utilisez des balises <g> imbriquées avec des transformations, vous devez convertir les coordonnées en utilisant getTransformToElement (..); (voir la documentation SVG)
Jochen Bedersdorfer
3
xlink:hrefest obsolète, maintenant c'est justehref
osvein
22

C'est une vieille question, mais ...

Sur FireFox (7+) et Chrome (14+), vous pouvez tirer svg_element vers le haut. Cela ne vous donne pas la liberté de contrôler entièrement l'axe z, mais c'est mieux que rien;)

Ajoutez simplement cet élément à nouveau.

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

Je pensais que ça allait jeter une erreur ou quelque chose comme ça.

appendChild == se remplacer == redessiner

CoR
la source
3
Pas du tout une erreur; appendChildsupprime d'abord de l'ancien parent, le cas échéant, même s'il est identique au nouveau parent, puis l'ajoute à la liste des enfants du nouveau parent.
Potatoswatter
5

Une autre solution non mentionnée est de mettre chaque élément svg / ensemble d'éléments dans un div. Vous pouvez facilement modifier le z-index des divs.

Fiddle: cycles d'éléments SVG avec z-index pour les conteneurs

... Appuyez sur les boutons pour «pousser» cet élément vers l'avant. (vs repeindre l'ensemble et pousser 1 élément vers l'avant, mais en gardant l'ordre d'origine comme dans la solution acceptée)

Ce serait très bien d'avoir des indices z relatifs ...

stackOverflow veut que je mette le code si c'est un lien de jsfiddle? ... ook

Roman Rekhler
la source
5

Oui, l'ordre est ce qui spécifie quel objet sera devant l'autre. Pour manipuler l'ordre, vous devrez déplacer des éléments dans le DOM. Il y a un bon exemple de cela sur le wiki SVG à https://www.w3.org/TR/SVG11/render.html#RenderingOrder

Kelly Anderson
la source
4
Ce lien ne fonctionne plus. Ce lien explique la même idée: lien
Steve
4

Si vous utilisez la bibliothèque svg.js , vous pouvez utiliser la commande ".front ()" pour déplacer n'importe quel élément vers le haut.

Erel Segal-Halevi
la source
3

SVGutilise un «modèle de peintre» de rendu. La peinture est appliquée dans des opérations successives sur le périphérique de sortie de sorte que chaque opération peint sur une certaine zone du périphérique de sortie. Lorsque la zone chevauche une zone déjà peint la nouvelle peinture obscurcit partiellement ou complètement le old.- lien vers cette

Ishank
la source
3

En SVG, pour obtenir un index Z plus élevé, vous devez déplacer l'élément vers le bas dans l'arborescence DOM. Vous pouvez le faire avec jQuery, en sélectionnant l'élément SVG, en le supprimant et en l'ajoutant à nouveau à la position souhaitée:

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

Le commentaire d'Adam Bradley à la réponse de Sam était exactement pertinent. Il utilise jQuery plutôt que CSS uniquement, mais il a dit ceci:

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

Cependant, pour ce que je créais, j'avais besoin que mon chemin SVG soit au-dessus de tout autre chemin en survol, mais toujours en dessous de mon texte SVG. Alors, voici ce que j'ai trouvé:

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

AppendTo et insertBefore déplaceront votre élément vers un nouvel emplacement vous permettant de modifier la profondeur de l'élément SVG à volonté.

GRAPHIQUES FiSH
la source