getBBox()?

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

2 Likes

would this help? just bboxing :slight_smile:

http://svgjs.com/geometry/

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:

6 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

It would be awesome to put patterns like this in the docs somewhere - maybe an “advanced HTML” notebook? I tried a bunch of hacks to solve a similar problem before finding this thread by chance. Although it’s only a workaround, it lets you use a lot of existing JS/HTML in an Observable way.

As a future reference, I’ve built a function to get the BBox of a d3 selection, and set it as the dimensions of a rectangle, in this notebook:

Any suggestions or comments welcome

I’d like to use the convenience of SVGjs as well. The library is at https://svgjs.dev/, however.

I was able to import and draw a simple example using SVGjs, but getting the animation to work required refreshing the page after saving, for some reason.

@dlaliberte Would you mind creating a new topic for your issue? Thank you!