I'm trying to solve this problem for more than one day now, but I can't find an answer. My problem is that I need to scale an SVG image (responsive design). I need to manipulate the SVG code on the client side, so embedding it via img tag is not an option. Therefore I tried to use an inline image instead. However, to scale it properly it seems that I need to set the viewBox property. The SVG files are generated by some software which can't set the bounding box on it's own, so my idea was to use JavaScript for that purpose.
The problem is that my software uses various tab controls from a library which I can't modify. I can't just get the bounding box, because it's not rendered initially and therefore I just get back zeros (in Chrome) or error messages (in Firefox).
What I need is a way to get the size of the bounding box without actually rendering the object. It is not possible to manipulate the display parameter, which the library uses to show and hide tabs.
Any ideas?
One idea was to copy the SVG into another, visible div, but I don't know if that would solve the problem. And I don't know how to do it.
Best regards
The SVG files are generated by some software which can't set the bounding box on it's own, so my idea was to use JavaScript for that purpose. The problem is that my software uses various tab controls from a library which I can't modify.
const box = svg.querySelector("[name=content]").getBBox(); // Remove the SVG element from the DOM. svg.remove(); // Set the viewBox.
Note: If the visibility attribute is set to hidden on a text element, then the text is invisible but still takes up space in text layout calculations. Depending on the value of attribute pointer-events, graphics elements which have their visibility attribute set to hidden still might receive events.
The SVGGraphicsElement.getBBox () method allows us to determine the coordinates of the smallest rectangle in which the object fits. The coordinates returned are with respect to the current SVG space (after the application of all geometry attributes on all the elements contained in the target element).
Based on the previous answers, I monkeypatched getBBox
on my app init so it will transparently apply the hack.
Now I can call getBBox
directly on any element, whether it's attached or not.
_getBBox = SVGGraphicsElement.prototype.getBBox;
SVGGraphicsElement.prototype.getBBox = function() {
var bbox, tempDiv, tempSvg;
if (document.contains(this)) {
return _getBBox.apply(this);
} else {
tempDiv = document.createElement("div");
tempDiv.setAttribute("style", "position:absolute; visibility:hidden; width:0; height:0");
if (this.tagName === "svg") {
tempSvg = this.cloneNode(true);
} else {
tempSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
tempSvg.appendChild(this.cloneNode(true));
}
tempDiv.appendChild(tempSvg);
document.body.appendChild(tempDiv);
bbox = _getBBox.apply(tempSvg);
document.body.removeChild(tempDiv);
return bbox;
}
};
you can clone it to a visible svg and then getBBox.
Add into you html:
<div style="position:absolute;left:-9999cm;top:-9999cm;visibility:hidden;">
<svg id="svg1" xmlns="http://www.w3.org/2000/svg"></svg>
</div>
Add into your javascript:
function getBBox(elem){
var svg1 = document.getElementById('svg1'), e = elem.cloneNode(true);
e.style.display = "inline";
svg1.appendChild(e);
var b = e.getBBox();
svg1.removeChild(e);
return b;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With