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!

1 Like