🏠 back to Observable

getBBox()?

How can I best get hold of svg.node().getBBox()? It returns SVGRect {x: 0, y: 0, width: 0, height: 0}.

1 Like

would this help? just bboxing :slight_smile:

This issue is typically because you are calling element.getBBox before adding the element to the DOM; the browser can’t compute the bounding box of a detached element because it doesn’t know where it lives in the DOM and what styles will affect it.

The occurs commonly in Observable because the standard pattern is to implement cells as “pure” functions where you create detached elements and return them, and then they are inserted into the DOM; so within a cell, you should nearly always be working with detached elements. But you can workaround this issue by temporarily inserting the element into the body. For example:

{
  const svg = html`<svg style="border:solid 1px red;">
    <g name="content">
      <text>${DOM.text(text)}</text>
    </g>
  </svg>`;

  // Add the SVG element to the DOM so we can determine its size.
  document.body.appendChild(svg);

  // Computing the bounding box of the content.
  const box = svg.querySelector("[name=content]").getBBox();

  // Remove the SVG element from the DOM.
  svg.remove();

  // Set the viewBox.
  svg.setAttribute("width", box.width);
  svg.setAttribute("height", box.height);
  svg.setAttribute("viewBox", `${box.x} ${box.y} ${box.width} ${box.height}`);

  return svg;
}

Live example:

I use this technique to size the D3 radial tidy tree:

4 Likes

Thanks Mike! Will use that to auto-scale my X- Matrix.

Thanks RandomFractals. But importing another library make the notebook heavier and creates yet another dependency. So I’d rather opt for something inline, like Mike’s suggestion below.

my comment was mainly a suggestion you also explore other svg js libs

I see. Thanks. I’ve added svgjs.com to my exploration list.

1 Like