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

85

Angenommen, ich habe ein paar zusammengesetzte Formen ( <g>). Ich möchte in der Lage sein, sie anzuklicken und zu ziehen, aber ich möchte, dass der, den ich gerade ziehe, in der Z-Reihenfolge oben auf dem anderen liegt, so dass, wenn ich ihn über den ANDEREN ziehe, der andere man sollte in den Schatten gestellt werden.

Corey Trager
quelle
siehe hier .
Eliran Malka
Mögliches Duplikat des SVG-Nachbestellungs-Z-Index (Raphael optional)
Eliran Malka

Antworten:

113

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.

Sam
quelle
1
@theonlygusti Elemente am Ende des Dokuments befinden sich oben. Wenn Sie jQuery verwenden, sollten Sie in der Lage sein, etwas wie$('#thing-i-want-on-top').appendTo('#my-svg');
Adam Bradley
Grundsätzlich gibt es also keine Möglichkeit, eine Form beim Schweben nach oben (Z-Achse) zu schweben…?
Chharvey
jQuery unterstützt das Ändern der Reihenfolge von SVG-Pfaden nicht.
Senthe
4
@chharvey, Sie können Dinge nach oben schweben lassen, indem Sie sie neu bestellen - neu anhängen. Hier ist ein elegantes Beispiel: codepen.io/osublake/pen/YXoEQe
Frazer Kirkman
36

Eine Alternative zum Verschieben von Elementen im Baum besteht darin, <use>Elemente zu verwenden , bei denen Sie das ändernxlink:href Attribut so , dass Sie die gewünschte z-Reihenfolge erhalten.

Hier ist ein alter Thread auf der Mailingliste von SVG-Entwicklern, in dem dieses Thema im Zusammenhang mit dem Wunsch diskutiert wird, einige Formen zu animieren.

Aktualisieren:

<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, wodurch es das vorderste Element ist. Wir können jedes der anderen Elemente als vorderstes Element auswählen, indem wir einfach das xlink:hrefAttribut ändern . Im obigen Beispiel haben wir den Kreis mit ausgewählt id="c1", wodurch er als oberstes Element angezeigt wird.

Siehe Geige .

Erik Dahlström
quelle
1
Diese Antwort wäre viel nützlicher mit einem Beispiel oder mit den Informationen aus dieser Mailingliste (die gated ist).
Kyeotic
3
Funktioniert, aber Sie müssen die Verwendung entsprechend hinzufügen. Wenn Sie Übersetzungen verwenden, hat <use> keine Ahnung davon
Jochen Bedersdorfer
@JochenBedersdorfer nicht sicher, was du meinst, wie hängen Übersetzungen mit der z-Bestellung zusammen?
Erik Dahlström
War nicht sehr klar darüber. Wenn Sie verschachtelte <g> -Tags mit Transformationen verwenden, müssen Sie die Koordinaten mit getTransformToElement (..) konvertieren. (siehe SVG-Dokumente)
Jochen Bedersdorfer
3
xlink:hrefist veraltet, jetzt ist es nurhref
osvein
22

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 der vollständigen Steuerung der Z-Achse, aber es ist besser als nichts;)

Fügen Sie dieses Element einfach erneut hinzu.

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 Irrtum auslösen oder so.

appendChild == sich selbst ersetzen == neu zeichnen

AdR
quelle
3
Überhaupt kein Fehler; appendChildEntfernt zuerst das alte übergeordnete Element, falls vorhanden, auch wenn es mit dem neuen übergeordneten Element identisch ist, und fügt es dann der untergeordneten Liste des neuen übergeordneten Elements hinzu.
Potatoswatter
5

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 einfach ändern.

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

... Drücken Sie die Tasten, um das Element nach vorne zu drücken. (vs 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 setze, wenn es sich um einen Link von jsfiddle handelt? ... ook

Roman Rekhler
quelle
5

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

Kelly Anderson
quelle
4
Dieser Link funktioniert nicht mehr. Dieser Link erklärt die gleiche Idee: Link
Steve
4

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

Erel Segal-Halevi
quelle
3

SVGverwendet ein "Malermodell" des Renderns. Farbe wird in aufeinanderfolgenden Operationen auf das Ausgabegerät aufgetragen, so dass jede Operation über einen bestimmten Bereich des Ausgabegeräts malt. Wenn der Bereich einen zuvor gestrichenen Bereich überlappt, verdeckt die neue Farbe die alte Verbindung teilweise oder vollständig

Ishank
quelle
3

Um in SVG einen höheren größeren Z-Index zu erhalten, sollten Sie das Element im DOM-Baum nach unten verschieben. Sie können dies mit jQuery tun, indem Sie das SVG-Element auswählen, es entfernen und an der gewünschten Position erneut anhängen:

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

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

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

Für das, was ich erstellt habe, musste sich mein SVG-Pfad beim Schweben über jedem anderen Pfad befinden, aber immer noch unter meinem SVG-Text. Also hier ist, was ich mir ausgedacht habe:

$('#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.

FiSH-GRAFIKEN
quelle