使用data()方法将键添加到d3.js图表​​中的嵌套元素

时间:2014-05-15 17:48:01

标签: javascript d3.js

我正在构建一个d3.js图表​​,该图表在数据中有一定程度的嵌套,并且在应用data()函数时我在指定行的键时遇到问题。以下是对相关位的简单了解。

我的数据是这种形式:

[
    {
        name: 'United States',
        values: [ {year:1960, imports:12, exports:13}, etc... ]
    },
    {
        name: 'China',
        values: [ {year:1960, imports:10, exports:11}, etc... ]
    }
]

我创建了这样的基本图形:

var svg = d3.select(this).selectAll('svg').data([data]);
var g = svg.enter().append('svg').append('g').attr('class', 'main');
g = svg.select('g.main')

一切似乎都很好。对于数据中的每个国家/地区,我绘制了两行,因此我将它们组合在一起(as described in this answer)。

var lines_g = g.selectAll("g.lines")
                  .data(function(d) { return d; },
                        function(d) { console.log(d.name); return d.name; });
lines_g.enter().append("g").attr("class", "lines");

这似乎也很好 - 控制台显示'中国'和'美国'来自data()电话的关键部分。

但是我在为每个lines_g组中的线路添加密钥时苦苦挣扎。例如,这样做:

lines_g.selectAll('path.line.imports')
         .data(function(d) { return [d.values]; },
               function(d) { console.log(d); return d.name; })
         .enter().append('path')
           .attr('class', 'line imports');

控制台显示我希望通过记录d.values而非d而预期的数组:

[ {year:1960, imports:12, exports:13}, etc... ]

为什么我不能在那时访问d,因此d.name?并且,为组内的行提供与其组相同的键是否正确?

1 个答案:

答案 0 :(得分:1)

您正在处理嵌套选择。也就是说,您对每个国家/地区都有一个顶级选择,并且每个国家/地区都只选择一个值 - 这就是您在说

时所做的事情。
.data(function(d) { return [d.values]; })

在此之后,您只能直接访问d.values中的内容。您正在记录d的关键功能,将获得您之前指定的数组元素 - [d.values]

如果您需要访问父数据元素的名称,我建议您也将此信息放入子元素中。也就是说,每个{year: 1960, ...}也有一个name: 'China'成员。您可以使用以下代码实现此目的:

data.forEach(function(d) {
  d.values.forEach(function(e) {
    e.name = d.name;
  });
});

这会复制很多信息,但在您的情况下可能不是必需的。由于每个国家/地区只有一个数据元素,因此您可以直接传递[d]而不是[d.values]。这只需要调整行生成器的方式稍作改动,也可以访问键功能中的国家名称。

我已经从另一个问题修改了jsfiddle以执行here