如何找到文字标签的最大长度?我的代码返回93.8495px,但我可以看到最大的是246.8128px?
// Append legend labels.
var labels = svg.selectAll("text")
.data(pie(dataset))
.enter()
.append("text")
.text(function(d) {
return d.data[0];
})
var maxTextWidth = d3.max(labels, function() {
return labels.node().getComputedTextLength();
});
console.log(maxTextWidth);
labels.attr("font-family", "open-sans")
.attr("font-size", 16)
.attr("fill", "#333")
.attr("x", labelLeftMargin)
.attr("y", function(d, i) {
return (i * labelHeight) - ((labelHeight * dataset.length) / 2) + keyRadius;
})
答案 0 :(得分:4)
事实证明,D3 v4 会让事情变得更容易。我添加了简化的解决方案,它应该是新版本的首选解决方案。尽管如此,我仍会保留原始答案作为仍然在v3上的人的参考。另外,请查看帖子末尾的旁注,这对两个版本都有效。
OP的使用d3.max(array[, accessor])
在v4方面仍然不正确,如果出于其他原因而不是之前。选择lables
现在是plain JavaScript object,而不是像v3中那样的数组数组。另一方面,d3.max()
将处理数组,而不是对象。但是,与v3不同,v4通过selection.nodes()
方法提供了对选择节点的轻松访问,该方法返回其包含的节点的平面数组。 d3.max()
:
var maxTextWidth = d3.max(labels.nodes(), n => n.getComputedTextLength());
工作片段:
var labels = d3.selectAll("text");
var maxTextWidth = d3.max(labels.nodes(), n => n.getComputedTextLength());
console.log(maxTextWidth);
<script src="https://d3js.org/d3.v4.js"></script>
<svg width="400" height="400">
<text x="50" y="100" font-family="monospace">IIIIIIIIIII</text>
<text x="50" y="130" font-family="monospace">MMMMMMMMM</text>
<text x="50" y="200" font-family="open-sans">IIIIIIIIIII</text>
<text x="50" y="230" font-family="open-sans">MMMMMMMMM</text>
</svg>
您对d3.max(array[, accessor])
的使用不正确:该函数将返回给定数组中的最大值。虽然您的labels
选择是一个数组,但事情有点复杂。选择实际上是 array of arrays ,这就是为什么你的方法不会抛出错误但也不会返回有意义的结果。
此外,在你应该为数组的每个元素执行的回调中,你正在调用labels.node()
,它将始终返回选择的第一个节点,这显然不是你想要的。
虽然Mark的answer速度更快,但他的代码在分组选择上运行时会有一些限制。据我所知,在您的代码中并非如此,但获得最大文本宽度的更通用,更健壮的方法将是这样的:
function getMaxTextWidth() {
var maxTextWidth = 0;
labels.each(function() {
maxTextWidth = Math.max(maxTextWidth, this.getComputedTextLength());
});
return maxTextWidth;
}
受到马克关于偏好d3.max()
超过selection.each()
的评论的启发,我一直在思考,并想出了另一种利用D3自己的方法获得最大文字宽度的优雅方法:
function getMaxTextWidth2() {
return d3.max(d3.merge(labels), function(d) {
return d.getComputedTextLength();
});
}
这使用d3.merge()
展平数组,它构成了选择,将其移至d3.max()
,避免selection.each()
完成显式循环。虽然我从未在选择中看到d3.merge()
的使用,但它对原始选择没有任何影响,并且对于这些不关心分组的操作非常方便,只需要包含所有元素的平面数组选择中。
我想到的另一件事是,在获取文字宽度后,您正在操纵标签的属性font-family
和font-size
。这些更改显然会对最大文本宽度产生影响。从您提供的片段判断,目前尚不清楚这是否是故意的。
var labels = d3.selectAll("text");
function getMaxTextWidth() {
var maxTextWidth = 0;
labels.each(function() {
maxTextWidth = Math.max(maxTextWidth, this.getComputedTextLength());
});
return maxTextWidth;
}
console.log(getMaxTextWidth());
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="400" height="400">
<text x="50" y="100" font-family="monospace">IIIIIIIIIII</text>
<text x="50" y="130" font-family="monospace">MMMMMMMMM</text>
<text x="50" y="200" font-family="open-sans">IIIIIIIIIII</text>
<text x="50" y="230" font-family="open-sans">MMMMMMMMM</text>
</svg>
答案 1 :(得分:1)
您d3.max
来电是不正确的。它始终会返回标签选择中第一个text
的长度。相反,尝试:
var maxTextWidth = d3.max(labels[0], function(d) {
return d.getComputedTextLength();
});
完整的工作代码:
<!DOCTYPE html>
<html>
<head>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
<svg>
<text>;kladjflk;asdjflkjasdflkjasdfkl</text>
<text>adkljfalskdjflk;asdfjkldddddddddddddasdjrrrrrr</text>
<text>akl;dfjladksjf</text>
</svg>
<script>
var labels = d3.selectAll('text');
var maxTextWidth = d3.max(labels[0], function(d) {
return d.getComputedTextLength();
});
console.log(maxTextWidth)
</script>
</body>
</html>
&#13;
答案 2 :(得分:0)
如上所述,该解决方案仅在您刚刚加入数据时才有效。但是,如果您要访问以前配置的元素,例如通过
var labels = svg.selectAll("text");
所描述的解决方案不起作用,因为标签[0]将是未定义的。在这种情况下,一种解决方案是添加nodes()函数以获取所需的数组,然后省略d3.max调用中的数组索引说明符。
var labels = svg.selectAll("text").nodes();
.data();
var maxTextWidth = d3.max(labels, function(d) {
return d.getComputedTextLength();
});
答案 3 :(得分:0)
对于某些svg
中的大多数节点选择,其他答案更好。
然而,我怀疑很多人会(像我一样)专门问这个问题,以便找到图表轴上最大数字的文本长度。在这种情况下,您知道哪个项目是最大的,因为您绘制了图表。通常它将是最后一项;我们倾向于从最小数字开始绘制轴,并以最大数字结束。在这种情况下,您可以获得如下所示的最大文本长度:
const labels = yourGroovyAxis.selectAll('text')._groups[0];
const maxTextWidth = labels[labels.length - 1].getComputedTextLength();
如果您知道最大值将是第一项,则问题会更加简单。您只需使用select
。
const maxTextWidth = yourGroovyAxis.select('text').getComputedTextLength();
同样,这只回答了OP提出的问题空间的一个子集。但是,对于那些处于我所描述的情况的人来说,这个解决方案我更直接。