Doing Ajax updates in SVG breaks getBBox, is there

2020-07-08 06:20发布

I have an SVG page with some complex diagrams; I'm trying to add code that inserts even more complexity via an Ajax call on demand. This is mostly working, but the inserted nodes don't behave properly. In particular getBBox() fails on some elements, in Firefox the error is something like this:

uncaught exception: [Exception... "Component returned failure code: 0x80004005  (NS_ERROR_FAILURE) [nsIDOMSVGLocatable.getBBox]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: http://localhost:1555/svg-scripts.js :: addBackground :: line 91"  data: no]

The problem seems to be related to this one: https://bugzilla.mozilla.org/show_bug.cgi?format=multiple&id=612118 but in my case the objects are definitely rendered, I can see them.

Any insight or workarounds appreciated. Unfortunately I can't easily point to an example since this relies on a server interaction.

2条回答
The star\"
2楼-- · 2020-07-08 07:07

See https://bugzilla.mozilla.org/show_bug.cgi?id=612118 (SVGLocatable.getBBox() fails unless the SVG element it is applied to is attached and rendered).

You must put your element to SVG and style.display must be non-"none".

See also SVG 'getBBox' fails in a jQueryUI tab

I workaround issue by placing text at invisible area ([-1000; -1000]):

function SVGlibText(x, y, text) {
    this.value = document.createElementNS(SVGlibBase.svgNS, "text");
    this.value.setAttribute("x", x);
    this.value.setAttribute("y", y);
    this.value.textContent = text;
}
SVGlibText.prototype.moveTo = function(x, y) {
    this.value.setAttribute("x", x);
    this.value.setAttribute("y", y);
    return this;
}
SVGlibText.prototype.getW = function() {
    return this.value.getBBox().width;
}
SVGlibText.prototype.getH = function() {
    return this.value.getBBox().height;
}

var text = new SVGlibText(-1000, -1000, "Hello world!");

getting width/height:

var textW = text.getW();
var textH = text.getH();

and placing text to necessary position after calculation with width/height (which require width/height in order to determine position of text):

text.moveTo(off, off + textH);
查看更多
Melony?
3楼-- · 2020-07-08 07:10

The NS_ERROR_FAILURE error message, or

Exception { message: "", result: 2147500037, name: "NS_ERROR_FAILURE", ...}`)

also occurs if you try to calculate the bounding box of an SVGElement which is attached directly to the HTML DOM and does not have a parent SVGSVGElement. Examples (you can run the code in Scratchpad, Shift+F4 in Firefox):

text directly attached to body

This fails because <html><body><g></g></body></html> is not allowed.

var text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
document.body.appendChild(text)
text.getBBox()
/*
Exception: [Exception... "Failure"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: Scratchpad/2 :: <TOP_LEVEL> :: line 3"  data: no]
*/

text attached to svg

This works.

var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
var text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
svg.appendChild(text);
document.body.appendChild(svg)
text.getBBox()
/*
[object SVGRect]
*/
查看更多
登录 后发表回答