skip to Main Content

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


  1. Chosen as BEST ANSWER

    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

    <!DOCTYPE html>
    <html>
    <head>
    <style>
    .myRectangle1.myRectangle2 {
      fill: rgb(255,0,0);
      stroke-width: 3;
      stroke: rgb(0,0,0);
    }
    
    .myRectangle1 .myRectangle2 {
      fill: rgb(0,255,0);
      stroke-width: 2;
      stroke: rgb(0,0,0);
    }
    
    .myRectangle1 {
      fill: rgb(0,0,255);
      stroke-width: 1;
      stroke: rgb(0,0,0);
    }
    
    .myRectangle2 {
      fill: rgb(255,255,0);
      stroke-width: 4;
      stroke: rgb(0,0,0);
    }
    </style>
    </head>
    <body>
    
    <h2>SVG Rectangles with CSS</h2>
    
    <svg width="400" height="180">
      <rect class="myRectangle1 myRectangle2" width="300" height="100" x="50" y="40" />
    </svg>
    
    <svg class="myRectangle1" width="400" height="180">
      <rect class="myRectangle2" width="300" height="100" x="50" y="40" />
    </svg>
    
    <svg width="400" height="180">
      <rect class="myRectangle1" width="300" height="100" x="50" y="40" />
      <rect class="myRectangle2" width="200" height="80" x="100" y="70" />
    </svg>
    
    </body>
    </html>


  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search