In the following code, I create text svg elements, word-wrap it and then create bounding boxes based on the new (wrapped) text dimensions and recntagles. I was only able do it in the following way, and I would like to know if the code could not be simplified so that maybe the boxes are created in the same function as the text?
var a=settings.g.selectAll(".axislabel")
.data(featureData)
.join(
enter => enter.append("text")
.attr("x", d => d.label_coord.x)
.attr("y", d => d.label_coord.y)
.text(d => d.name)
.attr("dy", "0.35em")
.call(wrap, 60)
)
var x=settings.g.selectAll("text")
/getting the elements I just created
for(let a of x['_groups'][0])
{
//iterating through and create bounding boxes
var v=a.getBBox();
//createing rectangles based on the boundinx boxes
settings.g.selectAll("labelBack")
.data([a.textContent])
.join(
enter => enter.append("rect")
.attr("x", v.x)
.attr("y", v.y)
.attr("width", v.width)
.attr("height", v.height)
.attr("fill", "white")
.attr("opacity", 1)
.attr("stroke-width", 1)
.attr("stroke", "black")
);
When you use selection.join with a functional argument, the function that you pass in constructs the dom element you want. Thus, you've got a lot of flexibility in what you build. In particular, you can do something like
enter => {
let g = enter.append("g");
let rect = g.append("rect");
let text = g.append("text")
...Code to set the text
rect
.attr('height', ...Code to set the height)
.attr('width', ...Code to set the width)
This can work because the text was set by the time the rect is sized. You can see this in action in the code below.
Credit: While this is a little bit different, I based the code partly on Gerardo's answer here.
let pad = 2;
let w = 200;
let h = 100;
let svg = d3
.select('#viz')
.append("svg")
.attr("viewBox", [0, 0, w, h])
.style("max-width", `${640}px`)
.style('border', 'solid 1px black');
let data = [
{ x: 10, y: 20, text: "This" },
{ x: 56, y: 50, text: "should" },
{ x: 120, y: 20, text: "work" }
];
svg
.append("g")
.selectAll(null)
.data(data)
.join((enter) => {
let g = enter.append("g");
let rect = g.append("rect");
let text = g
.append("text")
.attr("x", (d) => d.x)
.attr("y", (d) => d.y)
.text((d) => d.text)
.call(wrap);
rect
.attr("x", (d) => d.x - pad)
.attr("y", (d) => d.y - d.bbox.height + 2 * pad)
.attr("width", (d) => d.bbox.width + 2 * pad)
.attr("height", (d) => d.bbox.height + 2 * pad)
.attr("fill", "#ddd")
.attr("stroke", "black");
});
function wrap(selection) {
selection.each(function (d) {
d.bbox = this.getBBox();
});
}
<div id="viz"></div>
<script src="https://d3js.org/d3.v7.min.js"></script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With