How can I best get hold of svg.node().getBBox()? It returns SVGRect {x: 0, y: 0, width: 0, height: 0}.
would this help? just bboxing
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:
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.
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!