details1
details1

Reputation: 335

How to manipulate the layer of a element in an existing SVG?

I'm using d3 to manipulate an existing svg. The svg appears to have multiple layers. I'm able to get a handle to an expected element and manipulate it with d3. However, the element is on a lower layer. For example, I can set stroke (border color) and stroke-width on the element through d3 and I can see the updated border expanding out from beneath a higher layer with the same shape.

I need to figure out how to dynamically change element layers as needed on the fly. I tried setting z-index style and attr to 999 for the layer I'm trying to raise. No other z-index attrs exist in the svg so my assumption was that setting an element z-index to 999 would most likely raise it to the top but this did not happen. This assumption was mainly based on my background in html/css.

Can you recommend some basic troubleshooting steps for this? Is svg layering implementation and manipulation more complex than what I have in mind? Can you recommend any resources or possible shortcuts?

Upvotes: 1

Views: 1372

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102174

There is no z-index in a SVG. In an SVG, the order of the elements defines the order of the "painting", and the order of the painting defines who goes on top. The specs are clear:

Elements in an SVG document fragment have an implicit drawing order, with the first elements in the SVG document fragment getting "painted" first. Subsequent elements are painted on top of previously painted elements.

Therefore, you'll have to reposition the elements. There is a very simple solution, just do:

selection.raise();

Raise re-inserts each selected element, in order, as the last child of its parent.

Here is a demo, hover over the circle to bring it to the top:

d3.selectAll("circle").on("mouseover", function(){
	d3.select(this).raise()
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="400" height=200>
	<circle cy="100" cx="80" r="60" fill="blue"></circle>
	<circle cy="100" cx="160" r="60" fill="yellow"></circle>
	<circle cy="100" cx="240" r="60" fill="red"></circle>
	<circle cy="100" cx="320" r="60" fill="green"></circle>
</svg>

Note that raise() will only work for elements in the same level (that is, having the same parent element).

Upvotes: 3

Related Questions