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


Sagen wir, 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 die eine, die ich gerade ziehe, in der Z-Reihenfolge oben auf der anderen ist, sodass ich sie über die andere ziehe, die andere man sollte verfinstert werden.


75
2018-01-27 02:11


Ursprung


Antworten:


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


102
2018-01-27 02:27



Eine Alternative zum Verschieben von Elementen im Baum ist zu verwenden <use> Elemente, wo Sie die ändern xlink:href Attribut, so dass es Ihnen die gewünschte z-Bestellung gibt.

Hier ist ein alter Faden auf der svg-developers Mailingliste, die dieses Thema im Zusammenhang mit dem Wunsch, einige Formen zu animieren, diskutiert.

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 Element <use> das letzte Element, das es zum vordersten Element macht. Wir können jedes der anderen Elemente so auswählen, dass es als vorderstes Element wirkt, indem wir einfach die xlink:href Attribut. Im obigen Beispiel haben wir den Kreis mit ausgewählt id="c1", wodurch es als oberstes Element erscheint.

Sehen Geige.


25
2018-06-09 08:03



Das ist alte Frage, aber ...

Auf FireFox (7+) und Chrome (14+) kannst du svg_element nach oben ziehen. Dies gibt Ihnen keine Freiheit der vollen Z-Achsensteuerung, aber es ist besser als nichts;)

Hängen Sie das Element einfach erneut 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 oder etwas werfen.

appendChild == Ersetze sich selbst == redraw


21
2017-11-07 23:46



Eine andere Lösung, die nicht erwähnt wird, besteht darin, jedes SVG Item / Set von Items in ein div zu legen. Sie können den Z-Index der divs einfach ändern.

Fiddle: SVG Elemente Zyklen mit Z-Index für Container

... Drücken Sie auf die Tasten, um das Element nach vorne zu schieben. (vs das ganze Set neu streichen und 1 Element nach vorne schieben, aber die ursprüngliche Reihenfolge beibehalten wie in der akzeptierten Lösung)

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

stackOverflow möchte, dass ich den Code stelle, wenn es ein Link von jsfiddle ist? ... 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>


4
2018-03-06 17:49



Wenn du das benutzt svg.js-BibliothekSie können den Befehl ".front ()" verwenden, um ein beliebiges Element nach oben zu verschieben.


4
2018-03-13 12:15



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


4
2018-01-27 02:49



SVG verwendet ein "Malermodell" zum Rendern. Farbe wird in aufeinanderfolgenden Vorgängen auf das Ausgabegerät aufgebracht, so dass jeder Vorgang einen Bereich des Ausgabegeräts überstreicht. Wenn der Bereich einen zuvor gestrichenen Bereich überlappt, verdeckt der neue Anstrich den alten teilweise oder vollständig. Link dazu


3
2018-01-16 13:03



Adam Bradleys Kommentar zu Sams Antwort war genau auf dem Punkt. Es verwendet jQuery und nicht nur CSS, aber er sagte dies:

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

Für das, was ich erstellt habe, brauchte ich jedoch meinen SVG-Pfad, um über jedem anderen Pfad zu stehen, aber immer noch unter meinem SVG-Text. Also hier ist, was ich herausgefunden habe:

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

Sowohl appendTo als auch insertBefore verschieben Ihr Element an einen neuen Ort, an dem Sie die Tiefe des SVG-Elements beliebig ändern können.


0
2017-08-26 11:54