我正在开发一个交互,诚然这不是 D3 的典型用途,但它对创建 4 部分叙事的前 3 个阶段并制作动画非常有帮助。在最后阶段,我希望用户能够在几个因素之间进行选择以进行排序。在每种情况下,排序都会导致每个<rect>
人都在两个组中的一个中。本质上,这只是一个分组条形图。
我认为图片比文字好,所以这里有两个例子:http ://thatmichael.com/sandbox/immigration/sample.png
问题是两组之间的差距很小。
如果所有的<rect>
s 都在同一内部<g>
,我认为这样会很容易:
d3.select("#theGroup").selectAll("rect")
.sort(function(a, b) {
return d3.ascending(a.party, b.party) || d3.ascending(a.lastName, b.lastName);
});
但我很想在小组之间保持空间,因为这真的有助于看到分歧。
另一个次优解决方案是以所有可能的方式嵌套数据,然后<rect>
使用新数据集删除并重绘所有 s。像这样的东西:
oldSenateByVote = d3.nest()
.key(function(d) {return d.vote;})
.sortKeys(d3.descending)
.entries(oldSenate);
var svg = d3.select("#barWrapper svg")
.attr("width", bar.w)
.attr("height", bar.h);
var g = svg.selectAll("g.groups")
.data(oldSenateByVote)
.enter()
.append("g")
.attr("class", "groups");
g.selectAll("rect")
.data(function(d) {return d.values})
.enter().append("rect")
.transition().duration(1000)
.attr("x", function(d, i) {
return i * (token.w + 1) + bar.paddingLeft;
});
.attr("y", bar.paddingTop)
.attr("width", token.w)
.attr("height", token.h)
.each(function(d, i) {
if (d.party == "R") {
d3.select(this).attr("class", "token gop");
} else {
d3.select(this).attr("class", "token dem");
}
});
但是由于从来没有任何元素进入或退出,所以最好让对象保持不变。
有谁知道这样做的方法?或者至少是假的?也许答案是只为<rect>
一个“组”中的所有 s 添加一个类,并使用它手动将该组移动超过 10 像素,尽管这看起来真的很hack-ish。