d3.selectAll 输入嵌套键值对的退出 -- 又名:数组选择如何工作?



我有一个嵌套的数据数组,用于创建分组条形图。我在为嵌套数组的数据连接分配键时遇到问题。

下面是输入数据、顶层的工作数据联接以及我试图完成的两个部分实现。我离得很近!

// input data    
var data = [
{"key":"cat1","value":[{"key":"subcatA","value":100},{"key":"subcatB","value":200}]},
{"key":"cat2","value":[{"key":"subcatA","value":150},{"key":"subcatB","value":250}]}
];

要访问顶层并构建主要类别,我这样做:

// top level (all good)
var plot = d3.select('#plot');
plot.selectAll(".category")
.data(data,function(d) {return d.key;}) // <-- return key on datajoin
.enter().append("g")
.attr("class", "category")

在 datajoin 上返回d.key会跟踪每个类别,这样 enter() 和 exit() 就不会是一团乱七八糟的动画。请参阅 Mike Bostock 的常规更新模式,II,以获取有关向数据连接添加键的参考。

为了绘制第二关,我这样做:

// second level (plots but no key is assigned)
plot.selectAll(".category").selectAll(".bar")
.data(function (d) {return d.value; }) // <-- is this right?
.enter().append("rect")
.attr("class","bar")

没有分配密钥,因此 d3 相当随机地处理更新。如果我这样做,我只能在第一次迭代中获得我想要的东西:

// second level (key is assigned but first iteration only)
plot.selectAll(".g-category").selectAll(".bar")
.data(data[0].value, function (d) {return d.key; }) // <-- first category only
.enter().append("rect")
.attr("class","bar")

完美,除了我需要迭代data,而不仅仅是data[0]。我的问题是,一旦我尝试,我就会与d3.selectAll发生利益冲突,把事情弄得一团糟。

这个问题的答案可能很简单,但我错过了它:如何正确选择键并将其分配给 d3 中的嵌套数组?

第二级中的数据方法只有一个参数:

.data(function (d) {
return d.value; 
});

要分配键函数,您必须传递第二个参数。例如:

.data(function(d) {
return d.value
}, function(d) {
return d.key
});

您可以在一行中更好地看到它:

.data(function(d) { return d.value }, function(d) { return d.key });
//2nd arg after the comma ----------^

但是,为了便于人类阅读,我建议您为级别 1 和级别 2 使用不同的属性名称。现在一切都valuekey,这可能很难理解(尽管不适用于机器)。例如,在上面的代码片段中,value指的是第一级数组,而key指的是第二级数组,而不是第一级数组......你看到烂摊子了吗?

以下是包含您的数据的演示:

var data = [{
"key": "cat1",
"value": [{
"key": "subcatA",
"value": 100
}, {
"key": "subcatB",
"value": 200
}]
},
{
"key": "cat2",
"value": [{
"key": "subcatA",
"value": 150
}, {
"key": "subcatB",
"value": 250
}]
}
];
var body = d3.select("body");
var outer = body.selectAll(null)
.data(data, function(d) {
return d.key
})
.enter()
.append("div")
.attr("class", "outer");
var inner = outer.selectAll(null)
.data(function(d) {
return d.value
}, function(d) {
console.log("the key is: " + d.key)
return d.key
})
.enter()
.append("div")
.html(function(d) {
return d.key + " - " + d.value
});
<script src="https://d3js.org/d3.v4.min.js"></script>

最新更新