web-dev-qa-db-fra.com

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

Disons que j'ai quelques formes composites (<g>). Je veux pouvoir 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 il faut être éclipsé.

81
Corey Trager

L'index Z en SVG est défini par l'ordre d'apparition des éléments dans le document. Vous devrez modifier l'ordre des éléments si vous souhaitez apporter une forme spécifique au sommet.

108
Sam

Une alternative au déplacement d'éléments dans l'arborescence consiste à utiliser <use> éléments dont vous modifiez le xlink:href attribut pour qu'il vous donne l'ordre z que vous souhaitez.

Voici une ancienne discussion sur la liste de diffusion svg-developers discutant de ce sujet dans le contexte de vouloir 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 l'un des autres éléments pour agir en premier plan simplement en changeant le xlink:href attribut. 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 .

32
Erik Dahlström

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 complètement 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.

appendChild == se remplacer == redessiner

21
CoR

Une autre solution non mentionnée est de mettre chaque élément/ensemble d'éléments svg 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

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>
5
Roman Rekhler

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.

4
Erel Segal-Halevi

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

4
Kelly Anderson

SVG utilise un "modèle de peintre" de rendu. La peinture est appliquée en opérations successives sur le périphérique de sortie de telle sorte que chaque opération peint sur une certaine zone du périphérique de sortie. Lorsque la zone chevauche une zone précédemment peinte, la nouvelle peinture masque partiellement ou complètement l'ancienne.- lien vers cela

3
Ishank

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');
2
Agu Dondo

Le commentaire d'Adam Bradley à la réponse de Sam était exactement sur le point. 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 vol stationnaire, mais toujours en dessous de mon texte SVG. Voici donc 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é.

1
FiSH GRAPHICS