我的数据看起来像这样......
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很新,所以我可能会遗漏一些重要的东西。
答案 0 :(得分:12)
使用rangeBands和rangePoints,您必须定义域才能访问该范围。域告诉序数比例要显示多少个波段或点。但是,您可以稍后更改域名(通过调用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