With JavaScript, can I change the Z index / layer of an SVG <g> element?
Say I have a couple of composite shapes ( <g> ). I want to be able to click and drag them, but I want the one with which I am dragging now to be on top of the other in Z order, so if I drag it over OTHER, the other needs to be eclipsed.
The z-index in SVG is determined by the order in which the elements appear in the document. You will need to reorder the elements if you want to move a specific shape to the top.
An alternative to moving items in a tree is to use <use> elements in which you change the xlink:href attribute to give you the z-ordering you want.
Here's the old thread on the svg-developers mailing list discussing this issue in the context of the need to animate some shapes.
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 this example, the <use> element is the last, making it the most front element. We can select any of the other elements to act as the very front by simply changing the xlink:href attribute. In the above example, we selected a circle with id="c1" , which makes it the topmost element.
See fiddle .
This is an old question, but ...
In FireFox (7+) and Chrome (14+) you can bring svg_element to the beginning. This does not give you the freedom to fully control the z axis, but it is better than nothing;)
Just add this item again.
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 I thought this was going to throw an error or something like that.
appendChild == replace self == redraw
Yes, order is what indicates which object will be in front of another. To control the order, you will need to move things to the DOM. Here is a good example of this in the SVG wiki: https://www.w3.org/TR/SVG/render.html#RenderingOrder
Another solution that hasn't been mentioned before is to put each element / set of svg elements in a div. You can easily change the z-index of the div.
Fiddle: SVG element loops with z-index for containers
... Click on the buttons to βpushβ this element to the foreground. (vs repaints the entire set and pushes 1 element to the foreground, but retains the original order, as in the decision made)
It would be nice to have relative z-indices ...
stackOverflow wants me to put the code if this is a link from jsfiddle? ... 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> If you use svg.js library , you can use the ".front ()" command to move any item to the beginning.
SVG uses the "artist model" rendering. Paint is applied in sequential operations to the output device, so that each operation is drawn on a certain area of ββthe output device. When an area overlaps a previously painted area, the new paint partially or completely covers the old. reference to it
Adam Bradley's comment on Sam's answer was exactly in place. It uses only jQuery, not just CSS, but he said the following:
$('#thing-i-want-on-top').appendTo('#my-svg'); However, for what I created, I need my SVG path to be higher than any other path on hover, but still below my SVG text. So here is what I came up with:
$('#thing-i-want-on-top').insertBefore('#id-for-svg-text'); Both appendTo and insertBefore move your element to a new location, allowing you to change the depth of the SVG element as you wish.
In SVG, in order to get a higher Z index, you have to move the element down in the DOM tree. You can do this with jQuery by selecting the SVG element, deleting it and adding it again to the desired position:
$('g.element').remove().appendTo('svg');