在SVG中进行Ajax更新会破坏getBBox,有解决方案吗?

时间:2022-11-20 18:13:39

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:

我有一个包含一些复杂图的SVG页面;我正在尝试添加代码,通过Ajax调用按需插入更复杂的代码。这主要是工作的,但是插入的节点不能正常工作。特别是getBBox()在某些元素上失败,在Firefox中错误如下:

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.

问题似乎与此相关:https://bugzilla.mozilla.org/show_bug.cgi?format=multiple&id=612118,但在我的情况下,对象是绝对呈现的,我可以看到它们。

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

任何见解或方法都值得赞赏。不幸的是,我不能简单地指向一个示例,因为这依赖于服务器交互。

2 个解决方案

#1


7  

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).

参见https://bugzilla.mozilla.org/show_bug.cgi?id=612118 (SVGLocatable.getBBox())失败,除非它应用到的SVG元素被附加和呈现)。

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

必须将元素放到SVG和样式中。必须不显示“没有”。

See also SVG 'getBBox' fails in a jQueryUI tab

参见jQueryUI选项卡中的SVG“getBBox”失败

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

我通过在不可见区域放置文本来解决问题([-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);

#2


0  

The NS_ERROR_FAILURE error message, or

NS_ERROR_FAILURE错误消息,或

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):

如果您试图计算直接附加到HTML DOM并且没有父svgsvgsvgsvgsvgelement的SVGElement的边界框,也会发生这种情况。示例(您可以在Scratchpad中运行代码,在Firefox中Shift+F4):

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]
*/

#1


7  

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).

参见https://bugzilla.mozilla.org/show_bug.cgi?id=612118 (SVGLocatable.getBBox())失败,除非它应用到的SVG元素被附加和呈现)。

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

必须将元素放到SVG和样式中。必须不显示“没有”。

See also SVG 'getBBox' fails in a jQueryUI tab

参见jQueryUI选项卡中的SVG“getBBox”失败

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

我通过在不可见区域放置文本来解决问题([-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);

#2


0  

The NS_ERROR_FAILURE error message, or

NS_ERROR_FAILURE错误消息,或

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):

如果您试图计算直接附加到HTML DOM并且没有父svgsvgsvgsvgsvgelement的SVGElement的边界框,也会发生这种情况。示例(您可以在Scratchpad中运行代码,在Firefox中Shift+F4):

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]
*/