i can only generate one rect for the text i have. I dont know how to apply getBBox to multiple text elements so they can all have their own backgrounds. Does anyone know how i can accomplish this?
function jobsCreation() {
let enteringText = dataJobs
.enter()
.append("text")
.attr("x", function (d) { return d.posX })
.attr("y", function (d) { return d.posY })
.attr("id", "jobText")
.text(function (d) { return d.name });
let texts = d3.selectAll("#jobText");
let bbox = enteringText.node().getBBox();
console.log(bbox);
let rect = svg.append("rect")
.attr("x", bbox.x)
.attr("y", bbox.y)
.attr("width", bbox.width)
.attr("height", bbox.height)
.attr("id", "nodeBox")
.style("fill", "white")
.style("stroke", "black")
.style("stroke-width", "1.5px");
enteringText.raise();
}
CodePudding user response:
svg.append()
will create a single element and selection.node()
will only return a single node.
While selection.nodes()
will return an array all the nodes in a selection, we still need to append one rectangle for each node. To do this, we can use the array returned by selection.nodes()
as a data array for a enter cycle:
let enteringRects = svg.selectAll("rect")
.data(enteringText.nodes())
.enter()
.append("rect")
.attr("x", function(node) { return node.getBBox().x })
.attr("y", function(node) { return node.getBBox().y })
.attr("width", function(node) { return node.getBBox().width })
.attr("height", function(node) { return node.getBBox().height })
.style("fill", "white")
.style("stroke", "black")
.style("stroke-width", "1.5px")
.lower();
Now we create one rectangle for every text element we create. As the bound datum in this selection is a DOM element we can access getBBox() easily as it is now a property of the datum itself.
let data = d3.range(15).map(function(d) { return Math.floor(Math.random() * 150) });
let width = 500;
let height = 300;
let svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
let enteringText = svg.selectAll("text")
.data(data)
.enter()
.append("text")
.attr("x", function (d) { return Math.random() * width })
.attr("y", function (d) { return Math.random() * height })
.text(function (d) { return d });
let enteringRects = svg.selectAll("rect")
.data(enteringText.nodes())
.enter()
.append("rect")
.attr("x", function(node) { return node.getBBox().x })
.attr("y", function(node) { return node.getBBox().y })
.attr("width", function(node) { return node.getBBox().width })
.attr("height", function(node) { return node.getBBox().height })
.style("fill", "white")
.style("stroke", "black")
.style("stroke-width", "1.5px")
.lower();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>