我有嵌套数据,如下所示:
data
> key
> values
> date
> reldif
> absdif
线图中一切正常:
var line = svg.selectAll(".lines")
.data(data, function(d) { return d.key; })
.enter()
.append("g")
.attr("class", "lines")
.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.key); })
.style("stroke-width", 4)
然而,尝试对圆圈使用相同的技术,我失败了。据我所知,我需要x,y和r(可以是绝对的,就像5左右)。 X应该是日期,Y应该是reldif。我如何访问这些值?如果我只是使用d.values它会移交一个我无法用这种方式处理的数组。
(一般情况下 - 如果您对D3中嵌套数据的教程有任何建议,我很高兴听到这些建议。我发现除了将它们用于图表之外的所有主题)
答案 0 :(得分:2)
线条和圆圈之间存在根本区别 - 线条代表点的集合,而圆圈代表单个点。实际上,这意味着用于创建线的数据元素是一个数组,而它只是一个圆的单个数据点。
在您的示例中,您将数组(d.values
)传递给绘图基元。这对圆圈不起作用,因为它需要单个数据。你需要的是nested selections,它为属于同一“行”的圆圈引入了一个分组元素。代码看起来像这样。
svg.selectAll("g")
.data(data, function(d) { return d.key; })
.enter()
.append("g")
.selectAll("circle")
.data(function(d) { return d.values; })
.enter()
.append("circle")
.attr("cx", function(d) { return x(d.date); })
// etc
代码的第一部分是相同的,但在添加g
元素后,您正在为代表circle
元素的d.values
进行子选择。之后,代码很简单,并且以通常的方式附加circle
并进行配置。
一般情况下,嵌套数据用于图表的方式高度依赖于特定图表 - collapsible tree与chord diagram不同。有关嵌套选择的教程值得一读,但在这种特殊情况下,它不是嵌套数据的问题,而是不同图形元素所代表的不同问题。
答案 1 :(得分:1)
要处理嵌套数据,您可以创建nested selections。这里令人困惑的是lines
不需要任何嵌套选择。
这种绘制线条的方式在D3中有点特殊,因为它是使用path
SVG元素绘制的。 path
元素有一个属性d
accepts a DSL。这个字符串有点麻烦,因此D3提供了辅助对象d3.svg.line
。
在此辅助对象上,可以设置x
and y
accessors,它将决定构成该行的x
和y
点。此对象还允许您设置线的许多其他属性(如您想要的插值类型)。最后,可以将此辅助对象称为函数data
,它将生成路径的d
属性所需的DSL。
这是您在此处粘贴的示例中使用的方式:.attr("d", function(d) { return line(d.values); })
。在之前的某个地方,此line
对象是通过调用d3.svg.line
创建的,可能x
访问者设置为.x(function (d) { return d.date; })
,y
访问者设置为{{1 }}
注意:当您再次分配呼叫结果.y(function (d) { return d.reldif; }
时,您将覆盖line
变量。如果你这样做,JSHint会警告你。
现在line
元素相当简单。在这里,您不需要任何辅助函数,因为正如您所指出的,您可以直接设置circle
,x
和y
属性而无需中间DSL。因此,你会看起来像这样:
r
如果var circles = svg.selectAll(".circles")
.data(data, function(d) { return d.key; })
.enter()
.append("g")
.attr("class", "circles")
.selectAll(".circle")
.data(function (d) { return d.values; })
.enter()
.append("circle")
.attr("class", "circle")
.attr("cx", function(d) { return d.date; })
.attr("cy", function(d) { return d.reldif; })
.attr("r", 5)
.style("stroke", function(d) { return color(d.key); })
.style("stroke-width", 4)
实际上是d.values.date
个对象而不是数字,那么您可以使用time
scale将其转换为不错的数字。