【发布时间】:2016-06-24 16:32:42
【问题描述】:
我的介绍性问题是:
将数据绑定到 D3.js 地图的最佳方式是什么?
我想出了三种可能性:
1。根据数据应用一个类,然后将样式应用到该类。
.attr("class", function(d) { return quantize(rateById.get(d.id)); })
这个选项似乎是最流行的(参见choropleth 块),但它实际上并没有绑定数据。因此,D3 的意图似乎有点不诚实。这也意味着不能简单地引用绑定的数据作为工具提示。
2。将 topo.json 特征集合数据与其余数据合并。
我们可以将所有数据放在一个变量中(也许使用forEach)。结果可能类似于:
var mergeData = [{
area: "NW",
mean: 45,
features: {...}
}, {
area: "NE",
mean: 23,
features: {...}
}, {
area: "SW",
mean: 87,
features: {...}
}, {
area: "SE",
mean: 56,
features: {...}
}];
然后我们可以将mergeData绑定到路径元素,通过将“d”属性指向d.features生成地图,并使用d.mean设置样式。这允许每个路径元素包含我们将需要的所有必要数据。但是,将它们组合在一起似乎很麻烦。
3。将特征集合数据替换为所需数据。
一旦绘制了地图形状,就不再需要特征集合数据。它可以更换。为什么不简单地将我们需要的数据绑定到这些路径(在生成地图形状之后),以便它始终可用于样式、工具提示等?我们只需要一个关键函数来将新数据与正确的地图形状相匹配。更新选择将负责替换。
d3.selectAll(".area").data(data, function(d) {
return d.id;
})
.style("fill", function(d) {
return colorScale(d.mean);
});
这似乎运作良好,又好又干净。需要注意的是数据的结构和特征集合必须相同。在两组数据上评估相同的关键功能。所以如果我们的数据是嵌套的,我们就无法访问d.values.id,因为在特征集合中没有对应的values——它只是d.id。直观地说,我希望有一个类似于filter 的关键函数,这样我们就可以在每个数据集中指定id 的位置,如下所示:
return d.id === d.values.id;
没有办法做到这一点,是吗?
解决方法是将嵌套数据重构为第三个扁平数据变量,使其不再嵌套。这样d.id就可以用在key函数中了。但这又一次显得很麻烦。
最好的方法是什么?或者还有别的吗?
我仍在学习 D3,因此请随时纠正我的任何假设或直接编辑我的问题。
【问题讨论】:
-
我不确定你的意思。在 choropleth 示例中,数据绑定到
path元素。这不是你想要的吗? -
我投票给选项#2,这似乎是更直接的方法,可以应用于任何情况。但这只是其他可能的观点。
-
@LarsKotthoff 也许我遗漏了一些东西,但我没有看到任何绑定到
path元素的数据。如果我运行d3.selectAll(".q7-9").data(),我会得到一个空数组。是的,路径已根据数据填充颜色。但据我所知,它并没有受到约束。正如我上面提到的,这意味着您不能简单地选择路径并引用d来生成工具提示。 -
您可以通过检查 DOM 来检查
path元素是否有__data__成员。 -
据我所知,他们没有
__data__成员。我也没有在页面上的代码中看到任何添加新数据的内容——只有原始的topojson。
标签: javascript d3.js svg topojson