web-dev-qa-db-fra.com

Comment utiliser z-index dans les éléments svg?

J'utilise les cercles svg dans mon projet comme ça,

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 120">
    <g>
        <g id="one">
            <circle fill="green" cx="100" cy="105" r="20" />
        </g>
        <g id="two">
            <circle fill="orange" cx="100" cy="95" r="20" />
        </g>
    </g>
</svg>

Et j'utilise l'index z dans la balise g pour montrer les éléments en premier. Dans mon projet, je dois utiliser uniquement la valeur z-index, mais je ne peux pas utiliser l'index z pour mes éléments svg. J'ai beaucoup cherché sur Google mais je n'ai rien trouvé relativement. Alors aidez-moi à utiliser z-index dans mon svg.

Voici le DEMO.

131
Karthi Keyan

Spécification

Dans la spécification SVG version 1.1, l'ordre de rendu est basé sur l'ordre du document:

first element -> "painted" first

Référence à la Spécification SVG 1.1

.3 Ordre de rend

Les éléments d'un fragment de document SVG ont un ordre de dessin implicite, les premiers éléments du fragment de document SVG étant obtenus " peint "en premier . Les éléments suivants sont peints sur des éléments déjà peints.


Solution (plus rapide plus propre)

Vous devriez mettre le cercle vert comme dernier objet à dessiner. Alors permutez les deux éléments.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="30 70 160 120"> 
   <!-- First draw the orange circle -->
   <circle fill="orange" cx="100" cy="95" r="20"/> 

   <!-- Then draw the green circle over the current canvas -->
   <circle fill="green" cx="100" cy="105" r="20"/> 
</svg>

Voici la fourchette de votre jsFiddle .

Solution (alternative)

La balise use avec l'attribut xlink:href et comme valeur l'identifiant de l'élément. Gardez à l'esprit que cela pourrait ne pas être la meilleure solution même si le résultat semble correct. Ayant un peu de temps, voici le lien de la spécification SVG 1.1 "use" Element .

Objectif:

Pour éviter d’imposer aux auteurs de modifier le document référencé afin d’ajouter un ID à l’élément racine.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="30 70 160 120">
    <!-- First draw the green circle -->
    <circle id="one" fill="green" cx="100" cy="105" r="20" />
    
    <!-- Then draw the orange circle over the current canvas -->
    <circle id="two" fill="orange" cx="100" cy="95" r="20" />
    
    <!-- Finally draw again the green circle over the current canvas -->
    <use xlink:href="#one"/>
</svg>

Notes sur SVG 2

Spécification SVG 2 est la prochaine version majeure et prend toujours en charge les fonctionnalités ci-dessus.

.4. Ordre de rend

Les éléments en SVG sont positionnés en trois dimensions. En plus de leur position sur les axes x et y de la fenêtre de visualisation SVG, les éléments SVG sont également positionnés sur l'axe z. La position sur l'axe des z définit l'ordre dans lequel ils sont peints .

Sur l’axe des z, les éléments sont regroupés dans des contextes d’empilement .

.4.1. Établissement d'un contexte d'empilement dans SVG

...

Les contextes d'empilement sont des outils conceptuels utilisés pour décrire l'ordre dans lequel les éléments doivent être superposés lors du rendu du document, ...

142
Maicolpt

Essayez d'inverser #one et #two. Regardez ce violon: http://jsfiddle.net/hu2pk/3/

Update

En SVG, z-index est défini par l'ordre d'affichage de l'élément dans le document . Vous pouvez également consulter cette page si vous souhaitez: https://stackoverflow.com/a/482147/1932751

28
Lucas Willems

Comme d'autres l'ont dit ici, z-index est défini par l'ordre dans lequel l'élément apparaît dans le DOM. Si réorganiser manuellement votre code HTML n'est pas une option ou serait difficile, vous pouvez utiliser D3 pour réorganiser les groupes/objets SVG.

Utilisez D3 pour mettre à jour l'ordre DOM et imiter la fonctionnalité Z-Index

Mise à jour de l'index Z de l'élément SVG avec D

Au niveau le plus élémentaire (et si vous n'utilisez pas d'ID pour autre chose), vous pouvez utiliser les ID d'élément en tant que remplaçant pour z-index et réorganiser avec ceux-ci. Au-delà de cela, vous pouvez laisser votre imagination se déchaîner.

Exemples d'extraits de code

var circles = d3.selectAll('circle')
var label = d3.select('svg').append('text')
    .attr('transform', 'translate(' + [5,100] + ')')

var zOrders = {
    IDs: circles[0].map(function(cv){ return cv.id; }),
    xPos: circles[0].map(function(cv){ return cv.cx.baseVal.value; }),
    yPos: circles[0].map(function(cv){ return cv.cy.baseVal.value; }),
    radii: circles[0].map(function(cv){ return cv.r.baseVal.value; }),
    customOrder: [3, 4, 1, 2, 5]
}

var setOrderBy = 'IDs';
var setOrder = d3.descending;

label.text(setOrderBy);
circles.data(zOrders[setOrderBy])
circles.sort(setOrder);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 100"> 
  <circle id="1" fill="green" cx="50" cy="40" r="20"/> 
  <circle id="2" fill="orange" cx="60" cy="50" r="18"/>
  <circle id="3" fill="red" cx="40" cy="55" r="10"/> 
  <circle id="4" fill="blue" cx="70" cy="20" r="30"/> 
  <circle id="5" fill="pink" cx="35" cy="20" r="15"/> 
</svg>

L'idée de base est:

  1. Utilisez D3 pour sélectionner les éléments SVG DOM.

    var circles = d3.selectAll('circle')
    
  2. Créez un tableau d'indices z avec une relation 1: 1 avec vos éléments SVG (que vous souhaitez réorganiser). Les tableaux Z-index utilisés dans les exemples ci-dessous sont des ID, des positions x et y, des rayons, etc.

    var zOrders = {
        IDs: circles[0].map(function(cv){ return cv.id; }),
        xPos: circles[0].map(function(cv){ return cv.cx.baseVal.value; }),
        yPos: circles[0].map(function(cv){ return cv.cy.baseVal.value; }),
        radii: circles[0].map(function(cv){ return cv.r.baseVal.value; }),
        customOrder: [3, 4, 1, 2, 5]
    }
    
  3. Ensuite, utilisez D3 pour lier vos index-z à cette sélection.

    circles.data(zOrders[setOrderBy]);
    
  4. Enfin, appelez D3.sort pour réorganiser les éléments dans le DOM en fonction des données.

    circles.sort(setOrder);
    

Exemples

enter image description here

  • Vous pouvez empiler par ID

enter image description here

  • Avec le SVG le plus à gauche en haut

enter image description here

  • Plus petit rayon en haut

enter image description here

  • Ou Spécifiez un tableau auquel appliquer z-index pour un ordre spécifique - dans mon exemple de code, le tableau [3,4,1,2,5] déplace/réordonne le troisième cercle (dans l'ordre HTML d'origine) au 1er rang dans le DOM, au 4e rang , 1er pour être 3ème, et ainsi de suite ...

24
Steve Ladavich

Vous pouvez utiliser tiliser .

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 120">
    <g>
        <g id="one">
            <circle fill="green" cx="100" cy="105" r="20" />
        </g>
        <g id="two">
            <circle fill="orange" cx="100" cy="95" r="20" />
        </g>
    </g>
    <use xlink:href="#one" />
</svg>

Le cercle vert apparaît en haut.
jsFiddle

20
Jose Rui Santos

Comme indiqué, les commandes svgs sont affichées dans l'ordre et ne prennent pas z-index en compte (pour l'instant). Peut-être simplement envoyer l'élément spécifique au bas de son parent afin qu'il soit rendu en dernier.

function bringToTop(targetElement){
  // put the element at the bottom of its parent
  let parent = targetElement.parentNode;
  parent.appendChild(targetElement);
}

// then just pass through the element you wish to bring to the top
bringToTop(document.getElementById("one"));

Travaillé pour moi.

Mise à jour

Si vous avez un groupe SVG imbriqué contenant des groupes, vous devez extraire l'élément de son parentNode.

function bringToTopofSVG(targetElement){
  let parent = targetElement.ownerSVGElement;
  parent.appendChild(targetElement);
}

Une fonctionnalité intéressante de SVG est que chaque élément contient son emplacement indépendamment du groupe dans lequel il est imbriqué: +1:

10
bumsoverboard

Il n'y a pas d'index z pour svgs. Mais svg détermine lesquels de vos éléments sont les plus importants par leur position dans le DOM. Ainsi, vous pouvez supprimer l'objet et le placer à la fin du svg, ce qui en fait le "dernier élément rendu". Celui-ci est ensuite rendu "topmost" visuellement.


tilisation de jQuery:

function moveUp(thisObject){
    thisObject.appendTo(thisObject.parents('svg>g'));
}

usage:

moveUp($('#myTopElement'));

en utilisant D3.js:

d3.selection.prototype.moveUp = function() {
    return this.each(function() {
        this.parentNode.appendChild(this);
    });
};

usage:

myTopElement.moveUp();

9
Hafenkranich

Utiliser D3:

Si vous souhaitez ajouter l'élément dans l'ordre inverse à l'utilisation des données:

.insert('g', ":first-child")

Au lieu de .append

Ajout d'un élément en haut d'un élément de groupe

8
Nathan Hensher

Utiliser D3:

Si vous souhaitez réinsérer chaque élément sélectionné, dans l'ordre, en tant que dernier enfant de son parent.

selection.raise()
7
Diso

Une autre solution consisterait à utiliser des div, qui utilisent zIndex pour contenir les éléments SVG.Comme ici: https://stackoverflow.com/a/28904640/4552494

5
Roman Rekhler

Les solutions propres, rapides et faciles affichées à la date de cette réponse ne sont pas satisfaisantes. Ils sont construits sur la déclaration erronée selon laquelle les documents SVG n'ont pas d'ordre z. Les bibliothèques ne sont pas nécessaires non plus. Une ligne de code peut effectuer la plupart des opérations pour manipuler l'ordre z des objets ou des groupes d'objets pouvant être nécessaires au développement d'une application déplaçant des objets 2D dans un espace x-y-z.

L'ordre Z existe bel et bien dans les fragments de document SVG

Ce qu'on appelle un fragment de document SVG est une arborescence d'éléments dérivés du type de nœud de base SVGElement. Le nœud racine d'un fragment de document SVG est un SVGSVGElement, qui correspond à une balise HTML5 <svg> . SVGGElement correspond à la balise <g> et permet de regrouper les enfants.

Avoir un attribut z-index sur le SVGElement comme dans CSS annulerait le modèle de rendu SVG. Les sections 3.3 et 3.4 de la Recommandation v1.1 du W3C SVG, 2e édition, indiquent que les fragments de document SVG (arborescences issues d'un SVGSVGElement) sont restitués à l'aide de ce que l'on appelle une première recherche en profondeur de l'arborescence . Ce schéma est un ordre z dans tous les sens du terme.

L’ordre Z est en réalité un raccourci de vision par ordinateur qui évite le besoin d’un vrai rendu 3D avec les complexités et les exigences informatiques du traçage de rayons. Équation linéaire de l'index z implicite des éléments d'un fragment de document SVG.

z-index = z-index_of_svg_tag + depth_first_tree_index / tree_node_qty

Ceci est important car si vous souhaitez déplacer un cercle situé au-dessus d'un carré, vous insérez simplement le carré avant le cercle. Cela peut être fait facilement en JavaScript.

Méthodes de prise en charge

Les instances SVGElement ont deux méthodes qui prennent en charge la manipulation simple et facile de l'ordre z.

  • parent.removeChild (enfant)
  • parent.insertBefore (child, childRef)

La réponse correcte qui ne crée pas de gâchis

Parce que la balise SVGGElement ( <g> ) peut être supprimée et insérée aussi facilement qu'un SVGCircleElement ou toute autre forme, couches d'image typiques des produits Adobe et SVGGElement permet d’implémenter facilement d’autres outils graphiques. Ce JavaScript est essentiellement une commande Move Below .

parent.insertBefore(parent.removeChild(gRobot), gDoorway)

Si la couche d'un robot dessiné en tant qu'enfant de SVGGElement gRobot était devant la porte dessinée en tant qu'enfants de SVGGElement gDoorway, le robot est maintenant derrière la porte car l'ordre z de la porte est désormais égal à un plus de l'ordre z du robot.

Une commande Déplacer au-dessus est presque aussi simple.

parent.insertBefore(parent.removeChild(gRobot), gDoorway.nextSibling())

Pensez simplement a = a et b = b pour vous en souvenir.

insert after = move above
insert before = move below

Laissant le DOM dans un état compatible avec la vue

Cette réponse est correcte car elle est minimale et complète et, à l'instar des composants internes des produits Adobe ou d'autres éditeurs graphiques bien conçus, laisse la représentation interne dans un état cohérent avec la vue créée par le rendu.

Approche alternative mais limitée

Une autre approche couramment utilisée consiste à utiliser CSS z-index en association avec plusieurs fragments de document SVG (balises SVG) avec des arrière-plans principalement transparents, sauf le dernier. Encore une fois, cela défait l'élégance du modèle de rendu SVG, rendant difficile le déplacement d'objets vers le haut ou le bas dans l'ordre z.


REMARQUES:

  1. ( https://www.w3.org/TR/SVG/render.html v 1.1, 2e édition, 16 août 2011)

    3.3 Ordre de rendu Les éléments d'un fragment de document SVG ont un ordre de dessin implicite, les premiers éléments du fragment de document SVG étant "peints" en premier. Les éléments suivants sont peints sur des éléments déjà peints.

    3.4 Comment les groupes sont rendus Les éléments de groupement tels que l’élément ‘g’ (voir Éléments de conteneur) ont pour effet de produire un canevas séparé temporaire initialisé en noir transparent sur lequel les éléments enfants sont peints. À la fin du groupe, tous les effets de filtre spécifiés pour le groupe sont appliqués pour créer un canevas temporaire modifié. Le canevas temporaire modifié est composé à l'arrière-plan, en tenant compte des paramètres de masquage et d'opacité définis au niveau du groupe.

4
Douglas Daseeco

Nous avons déjà 2019 et z-index n'est toujours pas pris en charge en SVG.

Vous pouvez voir sur le site support de SVG2 dans Mozilla que l'état de z-index - Non implémenté .

Vous pouvez également voir sur le site bug 360148 "Support de la propriété 'z-index' sur les éléments SVG" (Rapporté: Il y a 12 ans).

Mais vous avez 3 possibilités dans SVG pour le définir:

  1. Avec element.appendChild(aChild);
  2. Avec parentNode.insertBefore(newNode, referenceNode);
  3. Avec targetElement.insertAdjacentElement(positionStr, newElement); (Pas de support dans IE pour SVG)

Exemple de démonstration interactive

Avec tout cela 3 fonctions.

var state = 0,
    index = 100;

document.onclick = function(e)
{
    if(e.target.getAttribute('class') == 'clickable')
    {
        var parent = e.target.parentNode;

        if(state == 0)
            parent.appendChild(e.target);
        else if(state == 1)
            parent.insertBefore(e.target, null); //null - adds it on the end
        else if(state == 2)
            parent.insertAdjacentElement('beforeend', e.target);
        else
            e.target.style.zIndex = index++;
    }
};

if(!document.querySelector('svg').insertAdjacentElement)
{
    var label = document.querySelectorAll('label')[2];
    label.setAttribute('disabled','disabled');
    label.style.color = '#aaa';
    label.style.background = '#eee';
    label.style.cursor = 'not-allowed';
    label.title = 'This function is not supported in SVG for your browser.';
}
label{background:#cef;padding:5px;cursor:pointer}
.clickable{cursor:pointer}
With: 
<label><input type="radio" name="check" onclick="state=0" checked/>appendChild()</label>
<label><input type="radio" name="check" onclick="state=1"/>insertBefore()</label><br><br>
<label><input type="radio" name="check" onclick="state=2"/>insertAdjacentElement()</label>
<label><input type="radio" name="check" onclick="state=3"/>Try it with z-index</label>
<br>
<svg width="150" height="150" viewBox="0 0 150 150">
    <g stroke="none">
        <rect id="i1" class="clickable" x="10" y="10" width="50" height="50" fill="#80f"/>
        <rect id="i2" class="clickable" x="40" y="40" width="50" height="50" fill="#8f0"/>
        <rect id="i3" class="clickable" x="70" y="70" width="50" height="50" fill="#08f"/>
    </g>
</svg>
4
Bharata

Poussez l'élément SVG en dernier, de sorte que son z-index soit en haut. En SVG, il n’existe pas de propriété appelée z-index. essayez ci-dessous javascript pour amener l'élément en haut.

var Target = document.getElementById(event.currentTarget.id);
var svg = document.getElementById("SVGEditor");
svg.insertBefore(Target, svg.lastChild.nextSibling);

Cible: est un élément pour lequel nous devons l'amener au début svg: est le conteneur d'éléments

2
Vaseem AbdulSamad

c'est facile à faire:

  1. clone vos articles
  2. trier éléments clonés
  3. remplacer articles par cloné
function rebuildElementsOrder( selector, orderAttr, sortFnCallback ) {
        let $items = $(selector);
        let $cloned = $items.clone();
        
        $cloned.sort(sortFnCallback != null ? sortFnCallback : function(a,b) {
                let i0 = a.getAttribute(orderAttr)?parseInt(a.getAttribute(orderAttr)):0,
                    i1 = b.getAttribute(orderAttr)?parseInt(b.getAttribute(orderAttr)):0;
                return i0 > i1?1:-1;
        });

        $items.each(function(i, e){
            e.replaceWith($cloned[i]);
        })
}

$('use[order]').click(function() {
    rebuildElementsOrder('use[order]', 'order');

    /* you can use z-index property for inline css declaration
    ** getComputedStyle always return "auto" in both Internal and External CSS decl [tested in chrome]
    
    rebuildElementsOrder( 'use[order]', null, function(a, b) {
        let i0 = a.style.zIndex?parseInt(a.style.zIndex):0,
                    i1 = b.style.zIndex?parseInt(b.style.zIndex):0;
                return i0 > i1?1:-1;
    });
    */
});
use[order] {
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="keybContainer" viewBox="0 0 150 150" xml:space="preserve">
<defs>
    <symbol id="sym-cr" preserveAspectRatio="xMidYMid meet" viewBox="0 0 60 60">
        <circle cx="30" cy="30" r="30" />
        <text x="30" y="30" text-anchor="middle" font-size="0.45em" fill="white">
            <tspan dy="0.2em">Click to reorder</tspan>
        </text>
    </symbol>
</defs>
    <use order="1" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="0" y="0" width="60" height="60" style="fill: #ff9700; z-index: 1;"></use>
    <use order="4" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="50" y="20" width="50" height="50" style="fill: #0D47A1; z-index: 4;"></use>
    <use order="5" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="15" y="30" width="50" height="40" style="fill: #9E9E9E; z-index: 5;"></use>
    <use order="3" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="25" y="30" width="80" height="80" style="fill: #D1E163; z-index: 3;"></use>
    <use order="2" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="30" y="0" width="50" height="70" style="fill: #00BCD4; z-index: 2;"></use>
    <use order="0" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="5" y="5" width="100" height="100" style="fill: #E91E63; z-index: 0;"></use>
</svg>
0
tdjprog