9

我正在使用 d3.format("s") 和 d3.svg.axis.tickFormat 来很好地格式化带有 SI 单位(来自国际单位制)的刻度标签。它在大多数情况下工作得很好,除了某些值会遇到舍入错误并返回大量小数位(例如,1400,如 1400 * 0.001 = 1.4000000000000001)。

为了解决这个问题,我可以指定一个精度,例如 d3.format(".2s") 但这会在 1 更好的情况下强制使用 2 个有效数字。例如,如果我有刻度 [5000, 10000, 15000],我现在会看到 [5.0k, 10k, 15k]。最初,当我根本没有指定精度时,我得到了 [5k, 10k, 15k]。

我想知道是否可以指定最大精度,以便仅在有效位数超过指定的数字时才应用它?所以 5000 是 5k 而不是 5.0k。

4

2 回答 2

3

虽然 1400 * .001 是 1.4000000000000001,但 1400 / 1000 是 1.4;将整数乘以 10 的负幂(例如 0.001)可能会引入舍入误差,但将整数除以 10 的幂(例如 1000)似乎不会。或者至少,可能性较小?我已经在 fix-si-format-rounding 分支中实现了一个暂定修复。它是严格向后不兼容的,但由于该d3.formatPrefix功能没有记录,我认为在下一个补丁版本中包含它是安全的。

编辑:此修复程序在版本 2.9.2 中发布。

于 2012-04-26T05:27:23.113 回答
2

You can do this by placing an if/else statement in an anonymous function where you would output the text string. Within that if/else you can satisfy any condition that you want and create a function that parses your value. Here is an example:

var w = 30, h = 300;
var data = [
  {'point':1, 'value':100.005},
  {'point':2, 'value':20.010},
  {'point':3, 'value':1000},
  {'point':4, 'value':5000.099},
  {'point':5, 'value':6000.934},
  {'point':6, 'value':9000.888},
  {'point':7, 'value':500.22},
  {'point':8, 'value':5.123},
  {'point':9, 'value':50.022},
  {'point':10, 'value':7000.999}
];
var chart = d3.select("body").append("svg")
  .attr('class', 'chart')
  .attr("width", w * data.length - 1)
  .attr("height", h);

chart.selectAll('text')
  .data(data)
.enter().append('text')
  .attr('x', function(d, i) { return x(i); })
  .attr('y', function(d) { return h - y(d.value); })
  .attr('dx', '0.75em')
  .attr('dy', '-0.3em')
  .attr('text-anchor', 'start')
  .text(function(d) { 
    if(d.value > 5000) {
      // Define your formatting function to return SI units
      var si = d3.format('s');
      return String(si(d.value));
    } else {
      // Otherwise round to the nearest integer
      return String(d3.round(d.value, 0));
    }
  });

Hope that helps.

于 2012-04-25T23:32:52.890 回答