ChatGPT解决这个技术问题 Extra ChatGPT

With JavaScript, can I change the Z index/layer of an SVG <g> element?

Let's say I have a couple composite shapes (<g>). I want to be able to click and drag them, but I want the one I happen to be dragging at the moment to be on TOP of the other one in the Z order, so that if I drag it over the OTHER one, the other one should be eclipsed.


E
Edward

Z index in SVG is defined by the order the elements appear in the document (subsequent elements are painted on top of previous elements).

You will have to change the element order if you want to bring a specific shape to the top.


@theonlygusti Elements at the end of the document are at the top. If you're using jQuery, you ought to be able to use something like $('#thing-i-want-on-top').appendTo('#my-svg');
So, basically, there's no way to float a shape to the top (z-axis) on hover…?
jQuery doesn't support changing order of SVG paths.
@chharvey, you can float things to the top by re-ordering them - re-appending. Here is an elegant example: codepen.io/osublake/pen/YXoEQe
E
Erik Dahlström

An alternative to moving elements in the tree is to use <use> elements where you change the xlink:href attribute so that it gives you the z ordering you want.

Here's an old thread on svg-developers mailinglist discussing this topic in context of wanting 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 one, which makes it the frontmost element. We can choose any of the other elements to act as frontmost simply by changing the xlink:href attribute. In the above example we picked the circle with id="c1", which makes it appear as the topmost element.

See fiddle.


This answer would be much more useful with an example, or with the info from that mailing list (which is gated).
Works, but make you add use appropriately. If you use translations, has no idea about them
@JochenBedersdorfer not sure what you mean, how are translations related to z ordering?
Wasn't very clear about that. If you use nested -tags with transforms, you need to convert the coordinates using getTransformToElement(..); (see SVG docs)
xlink:href is deprecated, now it's just href
C
CoR

This is old question, but...

On FireFox (7+) and Chrome (14+) you can pull svg_element to the top. This does not give you freedom of full z axis control, but it's better than nothing ;)

Just append that element 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 it was going to throw en error or something.

appendChild == replace itself == redraw


Not an error at all; appendChild first removes from the old parent, if any, even if it's the same as the new parent, then adds it to the new parent's child list.
R
Roman Rekhler

Another solution not mentioned is to put each svg item/set of items into a div. You can alter the z-index of the divs easily.

Fiddle: SVG elements cycles with z-index for containers

...Press on the buttons to 'push' that element to the front. (vs repainting the whole set and pushing 1 element to front, but keeping the original order as in the accepted solution)

It would be very nice to have relative z indices...

stackOverflow wants me to put the code if it's 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

lime
cyan
fuchsia


P
Patrick

Yes the order is what specifies what object will be in front of the other. To manipulate the order you will need to move things about the DOM. There is a good example of this on the SVG wiki at https://www.w3.org/TR/SVG11/render.html#RenderingOrder


That link no longer works. This link explains the same idea: link
E
Erel Segal-Halevi

If you use the svg.js library, you can use the ".front()" command to move any element to the top.


P
Pixel Rubble

Adam Bradley's comment to Sam's answer was exactly on point. It uses jQuery rather than CSS only, but he said this:

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

However, for what I was creating, I needed my SVG Path to be above any other path on hover, but still be below my SVG Text. So here's what I came up with:

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

Both appendTo and insertBefore will move your element to a new location allowing you to change the depth of the SVG element at will.


I
Ishank

SVG uses a "painters model" of rendering. Paint is applied in successive operations to the output device such that each operation paints over some area of the output device. When the area overlaps a previously painted area the new paint partially or completely obscures the old.- link to this


A
Agu Dondo

In SVG, to get a higher larger Z index you should move the element down in the DOM tree. You can do this with jQuery, selecting the SVG element, removing it and appending it again at the position you want:

$('g.element').remove().appendTo('svg');