繁体   English   中英

如何在D3折线图上拟合可变长度刻度标签?

[英]How to fit variable length tick labels on a D3 line chart?

这是一个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 + ")");

示例图表

谢谢!

您可以通过附加最大标签的文本,测量它并在之后立即将其删除来完成此操作:

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 + ")");

在这里完成示例。

编辑:获取实际标签的最大长度需要更多参与,因为您必须生成它们(使用正确的格式)并测量它们。 当你测量实际显示的内容时,这是一种更好的方法。 代码类似:

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();

我在这里添加了刻度线的大小和刻度线和标签之间的填充。 这里有完整的例子。

假设您希望轴和绘图组合以填充固定空间,并且您的刻度标签将自动生成,鸡和蛋的问题可以防止这种情况被可靠地预先计算。

问题是刻度标签以及它们所需的空间取决于规模。 例如,时间尺度可以包括在较短域上的较长月份名称(例如“9月”),但是较短的月份名称或仅在长域上的年份。 但是,至少在相反的轴上,比例取决于范围的剩余空间,这取决于确定刻度标签后留下的空间。

在很多情况下,最小值和最大值可以让您了解最宽的刻度标签,并且可以使用Lars的方法 例如,如果域为-50到10,则这些域之间的任何刻度标签将更窄。 但这假设它们是整数! 另外,要注意' 漂亮 '的尺度; 如果你的最大值是8,D3可能会尝试制作最大的刻度标签10,这是一个更宽的字符串。

d3 v4 Lars方法的解决方案。

calculateMarginForYScaleTicks() {
    let maxWidth = 0;
    let textFormatter = d3.format(",");
    let tempYScale = d3
        .scaleLinear()
        .range([0, 0])
        .domain([0, d3.max(data, d => d.value)]);

    d3
        .select("#svg")
        .selectAll("text.foo")
        .data(tempYScale.ticks())
        .enter()
        .append("text")
        .text(d => textFormatter(d))
        .each(function() {
            maxWidth = Math.max(this.getBBox().width, maxWidth);
        })
        .remove();

    return maxWidth;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM