Czy za pomocą JavaScript mogę zmienić indeks / warstwę Z elementu SVG <g>?

85

Powiedzmy, że mam kilka kształtów złożonych ( <g>). Chcę móc je klikać i przeciągać, ale chcę, aby ten, który akurat przeciągałem, znajdował się na GÓRZE drugiego w kolejności Z, więc jeśli przeciągnę go na INNY, drugi jeden powinien zostać zaćmiony.

Corey Trager
źródło
zobacz tutaj .
Eliran Malka
możliwy duplikat zmiany kolejności SVG z-index (opcjonalnie Raphael)
Eliran Malka

Odpowiedzi:

113

Indeks Z w SVG jest definiowany przez kolejność elementów w dokumencie. Będziesz musiał zmienić kolejność elementów, jeśli chcesz przenieść określony kształt na górę.

Sam
źródło
1
@theonlygusti Elementy na końcu dokumentu znajdują się na górze. Jeśli używasz jQuery, powinieneś móc użyć czegoś takiego$('#thing-i-want-on-top').appendTo('#my-svg');
Adam Bradley
Więc w zasadzie nie ma sposobu, aby przesunąć kształt do góry (oś Z) po najechaniu kursorem…?
chharvey
jQuery nie obsługuje zmiany kolejności ścieżek SVG.
Senthe
4
@chharvey, możesz przenieść rzeczy na górę, zmieniając ich kolejność - ponownie dołączając. Oto elegancki przykład: codepen.io/osublake/pen/YXoEQe
Frazer Kirkman
36

Alternatywą dla przenoszenia elementów w drzewie jest użycie <use>elementów, w których zmieniasz xlink:hrefatrybut, tak aby uzyskać żądaną kolejność z.

Oto stary wątek na liście mailingowej svg-developers omawiający ten temat w kontekście chęci animowania niektórych kształtów.

Aktualizacja:

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

W tym przykładzie element <use> jest ostatnim, co czyni go pierwszym elementem. Możemy wybrać dowolny z pozostałych elementów, aby działał jako pierwszy, po prostu zmieniając xlink:hrefatrybut. W powyższym przykładzie wybraliśmy okrąg z id="c1", co sprawia, że ​​pojawia się jako najwyższy element.

Zobacz skrzypce .

Erik Dahlström
źródło
1
Ta odpowiedź byłaby znacznie bardziej przydatna na przykładzie lub w przypadku informacji z tej listy mailingowej (która jest zamknięta).
Kyeotic,
3
Działa, ale musisz odpowiednio dodać użycie. Jeśli używasz tłumaczeń, <use> nie ma o nich pojęcia
Jochen Bedersdorfer,
@JochenBedersdorfer nie jesteś pewien, co masz na myśli, w jaki sposób tłumaczenia są powiązane z porządkowaniem z?
Erik Dahlström
Nie było tego jasne. Jeśli używasz zagnieżdżonych tagów <g> z transformacjami, musisz przekonwertować współrzędne za pomocą metody getTransformToElement (..); (patrz dokumentacja SVG)
Jochen Bedersdorfer,
3
xlink:hrefjest przestarzały, teraz jest po prostuhref
osvein
22

To stare pytanie, ale ...

W FireFox (7+) i Chrome (14+) możesz przeciągnąć svg_element na górę. Nie daje Ci to swobody pełnej kontroli osi Z, ale jest lepsze niż nic;)

Po prostu dołącz ponownie ten element.

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

Myślałem, że spowoduje to błąd czy coś.

appendChild == zamień się == przerysuj

CoR
źródło
3
W ogóle nie jest to błąd; appendChildnajpierw usuwa ze starego rodzica, jeśli taki istnieje, nawet jeśli jest taki sam jak nowy rodzic, a następnie dodaje go do listy dzieci nowego rodzica.
Potatoswatter
5

Innym niewymienionym rozwiązaniem jest umieszczenie każdego elementu svg / zestawu elementów w div. Możesz łatwo zmienić indeks z elementów div.

Fiddle: cykle elementów SVG z indeksem z dla kontenerów

... Naciśnij przyciski, aby „wypchnąć” ten element do przodu. (vs przemalowanie całego zestawu i przesunięcie 1 elementu do przodu, ale z zachowaniem oryginalnej kolejności jak w przyjętym rozwiązaniu)

Byłoby bardzo fajnie mieć względne indeksy z ...

stackOverflow chce, żebym wstawił kod, jeśli jest to link z jsfiddle? ... ook

Roman Rekhler
źródło
5

Tak, kolejność określa, jaki przedmiot będzie znajdował się przed drugim. Aby manipulować kolejnością, będziesz musiał przenieść rzeczy na DOM. Dobry przykład tego można znaleźć na wiki SVG pod adresem https://www.w3.org/TR/SVG11/render.html#RenderingOrder

Kelly Anderson
źródło
4
Ten link już nie działa. Ten link wyjaśnia ten sam pomysł: link
Steve
4

Jeśli korzystasz z biblioteki svg.js , możesz użyć polecenia „.front ()”, aby przenieść dowolny element na górę.

Erel Segal-Halevi
źródło
3

SVGużywa „modelu malarzy” renderowania. Farba jest nakładana w kolejnych operacjach na urządzenie wyjściowe tak, że każda operacja maluje pewien obszar urządzenia wyjściowego. Kiedy obszar zachodzi na wcześniej pomalowany obszar, nowa farba częściowo lub całkowicie zasłania starą. - link do tego

Ishank
źródło
3

W SVG, aby uzyskać wyższy, większy indeks Z, należy przesunąć element w dół w drzewie DOM. Możesz to zrobić za pomocą jQuery, wybierając element SVG, usuwając go i dodając ponownie w żądanej pozycji:

$('g.element').remove().appendTo('svg');
Agu Dondo
źródło
2

Komentarz Adama Bradleya do odpowiedzi Sama był dokładnie na miejscu. Używa jQuery, a nie tylko CSS, ale powiedział tak:

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

Jednak w przypadku tego, co tworzyłem, potrzebowałem, aby ścieżka SVG znajdowała się nad każdą inną ścieżką po najechaniu kursorem, ale nadal znajdowała się poniżej tekstu SVG. Oto co wymyśliłem:

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

Zarówno appendTo, jak i insertBefore przeniesie Twój element do nowej lokalizacji, umożliwiając dowolną zmianę głębokości elementu SVG.

GRAFIKA FISH
źródło