设置 d3 图表的 y 轴以适合最宽的标签?
我正在用 d3 绘制折线图,一切正常.但是,我必须在图表区域的左侧留出足够的边距,以适应我认为可能是最宽 y 轴文本标签的任何内容.我想根据最宽的标签调整每个图表的空间.
I'm drawing line charts with d3 and it all works fine. However, I have to leave enough margin on the left of the chart area to fit whatever I think might be the widest y-axis text label. I'd like to adjust this space for each chart, depending on the widest label.
最初我以为我可以找到最大 y 值,创建一个隐藏的文本对象,计算出它的宽度,然后在创建图表时将该值用作左边距.有点讨厌,但它给了我一个价值.
Initially I thought I could find the maximum y value, create a hidden text object, work out how wide that is, and use that value for the left margin when creating the chart. A bit nasty, but it gets me a value.
但是,如果最大 y 值是1598.538",那么最顶部的 y 轴标签可能是1500"……也就是说,要窄得多.
However, if the maximum y value is, say "1598.538" the top-most y-axis label might be "1500"... ie, a lot narrower.
所以我想我想找到实际上是最顶层标签的宽度.但是如果不绘制图表和轴,测量宽度并再次真实绘制,我无法想到如何做到这一点.听起来很恶心!有没有一种不讨厌的方法来做到这一点?
So I guess I want to find the width of whatever will actually be the top-most label. But I can't think how to do that without drawing the chart and axis, measuring that width, and drawing it again for real. Which sounds nasty! Is there a non-nasty way to do this?
更新
这是我的代码的一部分,使用了 Lars 的建议,只是为了显示它适合的位置:
Here's part of my code, using Lars' suggestion, just to show where it fits in:
// I did have
// `.attr("transform", "translate(" + margin.left + "," + margin.top ")")`
// on the end of this line, but I've now moved that to the bottom.
var g = svg.select("g");
// Add line paths.
g.selectAll(".line").data(data)
.enter()
.append("path")
.attr("d", line);
// Update the previously-created axes.
g.select(".axis-x")
.attr("transform", "translate(0," + yScale.range()[0] + ")"))
.call(xAxis);
g.select(".axis-y")
.call(yAxis);
// Lars's suggestion for finding the maximum width of a y-axis label:
var maxw = 0;
d3.select(this).select('.axis-y').selectAll('text').each(function(){
if (this.getBBox().width > maxw) maxw = this.getBBox().width;
});
// Now update inner dimensions of the chart.
g.attr("transform", "translate(" + (maxw + margin.left) + "," + margin.top + ")");
推荐答案
您可以将所有内容放在 g
元素中,并根据最大宽度设置 transform
.类似于
You can put everything inside a g
element and set transform
based on the max width. Something along the lines of
var maxw = 0;
yAxisContainer.selectAll("text").each(function() {
if(this.getBBox().width > maxw) maxw = this.getBBox().width;
});
graphContainer.attr("transform", "translate(" + maxw + ",0)");
相关文章