是否可以在带有动态域的序数范围内使用rangeBand()?

时间:2012-04-15 04:45:01

标签: d3.js

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

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文档(here),您无需为序数规范指定域,并且在您尝试使用它时将填充它。在我的情况下,但是y(d.name)总是返回0并且y.rangeBand()引发异常,即使我看起来已经在缩放对象内部填充了域数组。

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

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

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

我对d3很新,所以我可能会遗漏一些重要的东西。

3 个答案:

答案 0 :(得分:12)

使用rangeBandsrangePoints,您必须定义域才能访问该范围。域告诉序数比例要显示多少个波段或点。但是,您可以稍后更改域名(通过调用scale.domain(newDomain))并且范围将更新。你不能通过将以前看不见的值传递给比例来隐式地做到这一点。无论如何,定义具有序数尺度的域通常是个好主意,这样你总能获得确定性行为。

答案 1 :(得分:2)

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

这样的事情
d3.scale.ordinal(d3.range(0,myData.length)).rangeBands([0,myRangeBound])

将每个数据元素映射到唯一的数组索引。请记住,在这种情况下,在设置比例之前,必要时应对数据进行排序,并且只要数据发生变化,您就必须重置域。定义渲染方法等通常很好,可以在新数据进入时重置比例并重绘所有内容,并在可能的情况下明确设置域。

答案 2 :(得分:1)

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

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