5

我的数据看起来像这样......

var data = [{name:'a', value : 97},
          {name:'b', value : 24},
          {name:'c', value : 10}];

我有一个像这样创建的序数比例......

var y = d3.scale.ordinal().rangeBands([0, 30 * data.length]);

我正在用它来创建一个像这样的基本图表......

    chart.selectAll("rect")
        .data(data)
        .enter().append("svg:rect")
        .attr("y", function(d,i){ return y(d.name);})
        .attr("width", function(d,i){ return x(d.value);})
        .attr("height", y.rangeBand());

根据 d3 文档(此处),您不必为序数比例指定域,并且在您尝试使用它时会填充它。然而,在我的情况下, y(d.name) 总是返回 0 并且 y.rangeBand() 引发异常,即使当我查看域数组已填充到缩放对象中时也是如此。

所以,我通过预先定义我的域来解决这个问题......

.domain(data.map(function (d){ return d.name;}))

但我希望能够动态添加到这个域,如果我现在这样做,它不会超出创建时设置的原始值。这甚至可能吗?

我对 d3 很陌生,所以我可能在这里遗漏了一些重要的东西。

4

3 回答 3

12

With rangeBands and rangePoints, you must define a domain in order to access the range. The domain tells the ordinal scale how many bands or points you want to display. However, you can change the domain later (by calling scale.domain(newDomain)) and the range will update. You just can't do that implicitly by passing a previously-unseen value to the scale. It's generally a good idea to define domains with ordinal scales anyway, so that you always get deterministic behavior.

于 2012-04-17T04:28:34.730 回答
2

域中的元素在强制转换为字符串时必须是唯一的,因此如果您将对象数组传递给域,则可能会出现意外结果。例如,如果每个对象的字符串表示形式看起来像“[object Object]”,d3 可能会将这些对象视为完全相同。我以前遇到过这个问题,我解决它的方法是做类似的事情

d3.scale.ordinal(d3.range(0,myData.length)).rangeBands([0,myRangeBound])

它将每个数据元素映射到唯一的数组索引。请记住,在这种情况下设置比例之前,如有必要,您的数据应进行排序,并且您必须在数据更改时重置域。通常最好定义一个渲染方法或类似的方法来重置比例并在新数据进入时重绘所有内容,并尽可能明确地设置域。

于 2012-06-29T02:45:42.037 回答
1

我在 d3 google 群组中找到了答案。显然,如果您使用 rangeBands() 或 rangePoints() 您必须已经定义了一个域。

http://groups.google.com/group/d3-js/browse_thread/thread/10387d8ecf7ee412

于 2012-04-16T19:50:07.850 回答