web-dev-qa-db-de.com

Kann ich mit JavaScript den Z-Index / Layer eines SVG <g> -Elements ändern?

Angenommen, ich habe ein paar zusammengesetzte Formen (<g>). Ich möchte in der Lage sein, sie zu klicken und zu ziehen, aber ich möchte, dass diejenige, die ich gerade ziehe, in der Z-Reihenfolge oben auf der anderen ist, so dass, wenn ich sie über die ANDERE ziehe, die andere man sollte verdunkelt werden.

81
Corey Trager

Der Z-Index in SVG wird durch die Reihenfolge definiert, in der die Elemente im Dokument angezeigt werden. Sie müssen die Elementreihenfolge ändern, wenn Sie eine bestimmte Form nach oben bringen möchten.

108
Sam

Eine Alternative zum Verschieben von Elementen in der Struktur besteht darin, <use> - Elemente zu verwenden, bei denen Sie das Attribut xlink:href So ändern, dass Sie die gewünschte z-Reihenfolge erhalten.

Hier ist ein alter Thread in der Mailingliste der svg-Entwickler, in der dieses Thema diskutiert wird, um einige Formen zu animieren.

Update:

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

In diesem Beispiel ist das <use> -Element das letzte, was es zum vordersten Element macht. Wir können jedes der anderen Elemente als vorderstes Element auswählen, indem wir einfach das Attribut xlink:href Ändern. Im obigen Beispiel haben wir den Kreis mit id="c1" Ausgewählt, wodurch er als oberstes Element angezeigt wird.

Siehe Geige .

32
Erik Dahlström

Das ist eine alte Frage, aber ...

In FireFox (7+) und Chrome (14+) können Sie svg_element nach oben ziehen. Dies gibt Ihnen nicht die Freiheit, die Z-Achse vollständig zu steuern, aber es ist besser als nichts;)

Hänge das Element einfach noch einmal an.

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

Ich dachte, es würde einen Fehler auslösen oder so.

appendChild == sich selbst ersetzen == neu zeichnen

21
CoR

Eine andere nicht erwähnte Lösung besteht darin, jedes svg-Element/jeden Satz von Elementen in ein div zu setzen. Sie können den Z-Index der Divs leicht ändern.

Geige: SVG-Elemente zyklieren mit Z-Index für Container

... Drücke auf die Knöpfe, um das Element nach vorne zu schieben. (anstatt das ganze Set neu zu streichen und 1 Element nach vorne zu schieben, aber die ursprüngliche Reihenfolge wie in der akzeptierten Lösung beizubehalten)

Es wäre sehr schön, relative Z-Indizes zu haben ...

stackOverflow möchte, dass ich den Code hinzufüge, wenn es sich um einen Link von jsfiddle handelt? ... 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

Wenn Sie die Bibliothek svg.js verwenden, können Sie mit dem Befehl ".front ()" ein beliebiges Element nach oben verschieben.

4

Ja, die Reihenfolge gibt an, welches Objekt sich vor dem anderen befindet. Um die Reihenfolge zu ändern, müssen Sie Dinge im DOM verschieben. Es gibt ein gutes Beispiel dafür im SVG-Wiki unter https://www.w3.org/TR/SVG/render.html#RenderingOrder

4
Kelly Anderson

SVG verwendet ein "Malermodell" für das Rendern. In aufeinanderfolgenden Vorgängen wird Farbe auf das Ausgabegerät aufgetragen, sodass bei jedem Vorgang ein bestimmter Bereich des Ausgabegeräts überstrichen wird. Wenn der Bereich einen zuvor bemalten Bereich überlappt, wird der alte durch den neuen teilweise oder vollständig verdeckt.- Link daz

3
Ishank

Um in SVG einen höheren Z-Index zu erhalten, müssen Sie das Element im DOM-Baum nach unten verschieben. Sie können dies mit jQuery tun, indem Sie das SVG-Element auswählen, entfernen und an der gewünschten Position erneut anfügen:

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

Adam Bradleys Kommentar zu Sams Antwort war genau richtig. Es benutzt jQuery anstatt nur CSS, aber er sagte dies:

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

Für das, was ich erstellt habe, musste mein SVG-Pfad über jedem anderen Pfad liegen, aber immer noch unter meinem SVG-Text. Ich habe mir also Folgendes ausgedacht:

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

Sowohl appendTo als auch insertBefore verschieben Ihr Element an eine neue Position, sodass Sie die Tiefe des SVG-Elements nach Belieben ändern können.

1
FiSH GRAPHICS