I’m working on this code that gets some data from a .JSON (at the moment embedded here in the code) and then draw some boxes with text and some connection lines.
I’d like to view the bounding box around the text when I set some kind of debug flag.
This is the related code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
margin: 0;
overflow: hidden;
}
svg {
display: block;
}
.label {
text-anchor: middle;
alignment-baseline: middle;
font-family: Arial, sans-serif;
font-size: 12px;
}
.label .debugBoundingBox {
fill: none; /* Transparent fill */
stroke-width: 0.5;
stroke: #ccc;
stroke-dasharray: 1, 1;
}
.connection {
stroke: #e74c3c; /* Red color for connection */
stroke-width: 2;
stroke-dasharray: 5, 5; /* Add dashed line effect */
}
</style>
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<svg id="dot-sequence"></svg>
<script>
class Label {
constructor(name, x, y, text) {
this.name = name;
this.x = parseInt(x); // Parse coordinates as integers
this.y = parseInt(y);
this.text = text;
}
draw(svg, showDebugBoundingBox) {
const textElement = svg.append("text")
.attr("class", "label")
.attr("x", this.x)
.attr("y", this.y)
.text(this.text);
const bbox = textElement.node().getBBox();
if (showDebugBoundingBox) {
const debugBBox = svg.append("rect")
.attr("x", bbox.x)
.attr("y", bbox.y)
.attr("width", bbox.width)
.attr("height", bbox.height)
.attr("class", "label debugBoundingBox")
}
}
}
class Connection {
constructor(label1, label2) {
this.label1 = label1;
this.label2 = label2;
}
draw(svg) {
svg.insert("line", ":first-child") // Insert line as the first child
.attr("class", "connection")
.attr("x1", this.label1.x)
.attr("y1", this.label1.y)
.attr("x2", this.label2.x)
.attr("y2", this.label2.y)
.attr("stroke-dasharray", "5, 5") // Add dashed line effect
.attr("stroke", "#e74c3c"); // Set red color for connection
}
}
function composer(labelData, connectionData, showDebugBoundingBox) {
const svg = d3.select("#dot-sequence")
.attr("width", 500)
.attr("height", 150);
const labels = labelData.map(data => new Label(data.name, data.x, data.y, data.text));
// Create connections and draw them
connectionData.forEach(data => {
const label1 = labels.find(label => label.name === data.start);
const label2 = labels.find(label => label.name === data.end);
if (label1 && label2) {
const connection = new Connection(label1, label2);
connection.draw(svg);
}
});
// Draw labels after connections
labels.forEach(label => label.draw(svg, showDebugBoundingBox));
}
const labelDataJSON = [
{ "name": "label1", "x": "50", "y": "50", "text": "Text 1" },
{ "name": "label2", "x": "150", "y": "100", "text": "Text 2" },
{ "name": "label3", "x": "250", "y": "50", "text": "Text 3" },
{ "name": "label4", "x": "350", "y": "100", "text": "Text 4" },
{ "name": "label5", "x": "450", "y": "50", "text": "Text 5" }
];
const connectionDataJSON = [
{ "start": "label1", "end": "label2" },
{ "start": "label2", "end": "label3" },
{ "start": "label3", "end": "label4" },
{ "start": "label4", "end": "label5" }
];
const showDebugBoundingBox = true; // Set to true to show debug boxes, false to hide
composer(labelDataJSON, connectionDataJSON, showDebugBoundingBox);
</script>
</body>
</html>
my goal is to style a bounding box around the text, but now I can only see a black box covering my text.
But if I change this piece:
if (showDebugBoundingBox) {
const debugBBox = svg.append("rect")
.attr("x", bbox.x)
.attr("y", bbox.y)
.attr("width", bbox.width)
.attr("height", bbox.height)
.attr("class", "label debugBoundingBox")
.attr("fill", "none") // Set fill to none
.style("stroke-width", 0.5)
.style("stroke", "#ccc")
.attr("stroke-dasharray", "1, 1");
}
all works as I want. Why can’t I use the .CSS styling in there?
Thank you
2
Answers
I created this playground to understand better and now it's clear my fault, according to the answer here that resolves my problem: https://stackoverflow.com/a/77802702/2071273
Your CSS selector is
.label .debugBoundingBox
, which means a.debugBoundingBox
that is a descendant of a.label
. You want.label.debugBoundingBox
, which means an element that has both classes applied.