在SVG图中,我创建由矩形和一些文本组成的节点元素。文本的数量可以有很大的不同,因此我想根据文本的宽度设置矩形的宽度。
这是使用D3.js(使用固定的宽度和高度值)创建矩形的方法:
var rects = nodeEnter.append("rect")
.attr("width", rectW)
.attr("height", rectH);
后跟文本元素:
var nodeText = nodeEnter.append("text")
.attr("class", "node-text")
.attr("y", rectH / 2)
.attr("dy", ".35em")
.text(function (d) {
return d.data.name;
});
nodeText // The bounding box is valid not before the node addition happened actually.
.attr("x", function (d) {
return (rectW - this.getBBox().width) / 2;
});
如您所见,当前我将文本放在可用空间的中心。然后,我尝试根据它们的文本设置rect的宽度,但是我从没有同时获得rect元素和文本HTML元素(对于getBBox())。这是我的尝试之一:
rects.attr("width",
d => this.getBBox().width + 20
);
但显然this
是错误的,因为它指的是rects
而不是文本。
这里正确的方法是什么?
答案 0 :(得分:6)
我将使用getComputedTextLength
来测量文本。我不知道D3.js中是否有与此等效的程序。我的答案是使用纯JavaScript,并假设rect和文本中心为{x:50,y:25},而您正在使用{{1} }
text{dominant-baseline:middle;text-anchor:middle;}
let text_length = txt.getComputedTextLength();
rct.setAttributeNS(null,"width",text_length )
rct.setAttributeNS(null,"x",(50 - text_length/2) )
svg{border:1px solid}
text{dominant-baseline:middle;text-anchor:middle;}
或者您可以使用<svg viewBox="0 0 100 50">
<rect x="25" y="12.5" width="50" height="25" stroke="black" fill="none" id="rct" />
<text x="50" y="25" id="txt">Test text</text>
</svg>
txt.getComputedTextLength()
答案 1 :(得分:2)
当您记得this
调用中的attr()
绑定引用关联的HTML(SVG)元素时,解决方案非常简单:
rects.attr("width",
d => this.parentNode.childNodes[1].getComputedTextLength() + 20;
);
rect是构成要显示的节点的SVG元素列表中的第一个元素。该节点的文本位于索引1(如来自append
调用的索引)。
答案 2 :(得分:0)
通常我会发表评论,但是我没有足够的声誉。
公认的答案具有正确的想法,但不管他如何编码,都行不通。第一个问题是,他使用箭头函数而不是匿名函数。在箭头功能中,this
具有不同的范围。因此,请在此处使用匿名函数。
第二个问题是问题中rect
和text
的顺序,如您在源代码中所见。由于rect
附加在text
之前,所以父节点还没有子text
。因此,您必须just append
rect
,然后附加text
并设置其attrs
,然后设置attrs
的{{1}}。因此解决方案是:
rect
注意:如果不需要参数var rects = nodeEnter.append("rect")
var nodeText = nodeEnter.append("text")
.attr("class", "node-text")
.attr("y", rectH / 2)
.attr("dy", ".35em")
.text(function (d) {
return d.data.name;
});
nodeText // The bounding box is valid not before the node addition happened actually.
.attr("x", function (d) {
return (rectW - this.getBBox().width) / 2;
});
rect
.attr('width', function () {
return this.parentNode.childNodes[1].getComputedTextLength();
})
.attr("height", rectH);
,则不必像我一样接受它。