Working with d3.js, I'm trying to create a set of nodes, append an SVG circle and text element to each node and then re-position the text element (set its dx and dy attributes). Specifically, I'd like to center the text element inside the SVG.
In my current implementation, the SVG elements are created/appended first, then I'm iterating over the nodes a second time to measure each text element and transform it accordingly:
///////////////////////////////////////
// Create node elements from data... //
///////////////////////////////////////
const canvas = document.getElementById("canvas");
const data_nodes = state.data.nodes;
const elements = canvas.svg
.append("g")
.attr("class", "nodes")
//////
.selectAll(".node") // <— create empty selection
.data(data_nodes)
.enter()
//////
.append("svg") // <— added nested SVG
.attr("class", "node");
////////////////////////////////
// ...append circle & text... //
////////////////////////////////
elements.append("circle").attr("r", (data) => data.size / 2);
elements.append("text").text((data) => data.text.content)
////////////////////
// ...center text //
////////////////////
for (let node of elements.nodes()) {
const textEl = node.querySelector("text");
const width = textEl.getBoundingClientRect().width;
const height = textEl.getBoundingClientRect().height;
//////
textEl.setAttribute("dx", (width / 2) * -1);
textEl.setAttribute("dy", height / 2);
}
This works, but I'm wondering if it's possible to reference the DOM node corresponding to each appended text element while/after appending it and dynamically setting dx/dy then?