Wanderer
Wanderer

Reputation: 592

D3 How can i replace a SVG element

I have an svg like

<svg>
<g>
  <rect x='0' y='0' height='20' width='20' class='shape rect'/>
  <text x='10' y='10' text-anchor='middle' alignment-baseline='middle'>A</text>
</g>
</svg>

On user input I am trying to replace the shape <rect> to a different shape (say a circle)

In my JS I have:

// New User Data
var myData = [{
  text:A,
  shape:'circle',
  x:10,
  y:10
}];

// Remove existing shape and replace with a new shape
var svg = d3.select('svg');
var g = svg.select('g');
var sh = g.select('.shape);
sh.remove();
var newsh = g.selectAll('.shape').data(myData);
newsh.enter().append('circle').attr({
  cx: function(d){ return d.x;},
  cy: funciton(d){ return d.y;},
  r:10
})
.classed('shape circle',true);

This appends a new item to the group after the <text> element covering up the text. How can I specify the position of the elements when building new data.

EDIT: FIDDLE

Upvotes: 0

Views: 1197

Answers (1)

altocumulus
altocumulus

Reputation: 21578

Using selection.append() will append the circle as the last child of its parent <g> element. Because SVGs elements are rendered in document order, this will cover the text which is located before the newly appended circle. You can use selection.insert("circle", ":first-child") to insert the circle before the first element in the group, and, hence, before the text element.

// New User Data
var myData = [{
  text:'A',
  shape:'circle',
  x:10,
  y:10
}];

// Remove existing shape and replace with a new shape
var svg = d3.select('svg');
var g = svg.select('g');
var sh = g.select('.shape');
sh.remove();
var newsh = g.selectAll('.shape').data(myData);
newsh.enter().insert('circle', ':first-child').attr({
  "cx": function(d){ return d.x;},
  "cy": function(d){ return d.y;},
  "r":10
})
.classed('shape circle',true);
text {
 fill: white;
}
<script src="https://d3js.org/d3.v3.js"></script>
<svg>
<g>
  <rect x='0' y='0' height='20' width='20' class='shape rect'/>
  <text x='10' y='10' text-anchor='middle' alignment-baseline='middle'>A</text>
</g>
</svg>

Upvotes: 2

Related Questions