这是一个JSFiddle:http://jsfiddle.net/8p2yc/(这里有一个稍微修改过的例子:http://bl.ocks.org/mbostock/3883245)
正如您在JSFiddle中看到的那样,沿y轴的刻度标签不适合svg。我知道我可以增加左边距,但问题是我不知道预先提供了什么数据。如果我只是使边距非常大,如果数字很短,图表看起来会很尴尬。
有没有办法在创建图表时预先计算最大标签宽度以正确设置边距?或者可能有一个完全不同的解决方案?
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 400 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
谢谢!
答案 0 :(得分:14)
您可以通过附加最大标签的文本来进行测量,然后立即将其删除:
var maxLabel = d3.max(data, function(d) { return d.close; }),
maxWidth;
svg.append("text").text(maxLabel)
.each(function() { maxWidth = this.getBBox().width; })
.remove();
然后您可以使用该宽度来翻译g
元素:
svg.attr("transform", "translate(" + Math.max(margin.left, maxWidth) + "," + margin.top + ")");
完整示例here。
编辑:获取实际标签的最大长度需要更多一些,因为您必须生成它们(使用正确的格式)并全部测量它们。这是一个更好的方法来做到这一点,因为你正在测量实际显示的内容。代码类似:
var maxWidth = 0;
svg.selectAll("text.foo").data(y.ticks())
.enter().append("text").text(function(d) { return y.tickFormat()(d); })
.each(function(d) {
maxWidth = Math.max(this.getBBox().width + yAxis.tickSize() + yAxis.tickPadding(), maxWidth);
})
.remove();
我将勾号线的大小和刻度线与标签之间的填充添加到此处的宽度。 here的完整示例。
答案 1 :(得分:1)
鸡蛋和鸡蛋问题可以防止这种情况被可靠地预先计算,假设您希望您的轴和绘图组合以填充固定空间,并且您的刻度标签将自动生成。
问题在于刻度标签以及它们所需的空间取决于比例。例如,时间尺度可以包括较短的域上较长的月份名称(例如,' 9月'),但是较短的月份名称或仅较长的域名的年份。但是,至少在相反的轴上,比例取决于范围的剩余空间,这取决于确定刻度标签后留下的空间。
在很多情况下,最小值和最大值可能会让您了解最宽的刻度标签,您可以使用Lars' method。例如,如果域为-50到10,则这些域之间的任何刻度标签将更窄。 但这假设他们是整数!另外,请注意' nice'秤;如果你的最大值是8,D3可能会尝试制作最大的刻度标签10,这是一个更宽的字符串。
答案 2 :(得分:1)
d3 v4解决Lars'方法
{{1}}