我正在使用d3.js渲染一个分组的条形图,我希望在点击图例时动画转换条形图(显示/隐藏不同的系列)。
从此。
也许还会改变比例
http://jsfiddle.net/0ht35rpb/202/
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color)
.on("click", function(d) {
console.log("d", d);
});
一些条形转换代码
bars.transition()
.attr("id", function(d){ return 'tag'+d.state.replace(/\s|\(|\)|\'|\,+/g, '');})
.attr("x", function(d) { return x(d.state); })
.attr("width", x.rangeBand())
.attr("y", function(d) {return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
bars.exit().remove();
其他分组条形图参考。
https://bl.ocks.org/mbostock/3887051
答案 0 :(得分:3)
有几种方法可以解决这个问题。您可以轻松使用输入/更新/退出周期,但与循环的典型使用相比,这有点复杂,因为嵌套元素和需要设置键以确保图表状态之间的平滑过渡。
在这种情况下,可能更容易简单地使用数组来保存要过滤掉的条形图,隐藏这些条形图,更新标尺以不使用这些按键'值,并更新剩余的条。
这需要每个图例项的onclick事件。单击时,在我们单击的函数中,我们管理过滤掉的(filtered
)项目数组,其中d
是与图例矩形关联的基准:
// add the clicked key if not included:
if (filtered.indexOf(d) == -1) {
filtered.push(d);
// if all bars are un-checked, reset:
if(filtered.length == keys.length) filtered = [];
}
// otherwise remove it:
else {
filtered.splice(filtered.indexOf(d), 1);
}
然后我们可以更新比例(我们需要x1
比例域中不在过滤数组中的所有键,因此newKeys
变量):
var newKeys = [];
keys.forEach(function(d) {
if (filtered.indexOf(d) == -1 ) {
newKeys.push(d);
}
})
x1.domain(newKeys).rangeRound([0, x0.bandwidth()]);
y.domain([0, d3.max(data, function(d) { return d3.max(keys, function(key) { if (filtered.indexOf(key) == -1) return d[key]; }); })]).nice();
然后我们可以选择我们的矩形,根据它们是隐藏还是显示进行过滤,并相应地更新:
var bars = svg.selectAll(".bar").selectAll("rect")
.data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })
// filter out bars:
bars.filter(function(d) {
return filtered.indexOf(d.key) > -1;
})
.transition()
.attr("x", function(d) {
return (+d3.select(this).attr("x")) + (+d3.select(this).attr("width"))/2;
})
.attr("height",0)
.attr("width",0)
.attr("y", function(d) { return height; })
.duration(500);
// update persistent bars:
bars.filter(function(d) {
return filtered.indexOf(d.key) == -1;
})
.transition()
.attr("x", function(d) { return x1(d.key); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.attr("width", x1.bandwidth())
.attr("fill", function(d) { return z(d.key); })
.duration(500);
这个解决方案可以多做一点" d3-ish"使用输入/更新/退出周期,但由于我们的元素数量相对固定,因此在许多其他情况下没有那么有用。
以上是上面的代码:
https://bl.ocks.org/andrew-reid/64a6c1892d1893009d2b99b8abee75a7
如评论中所述,您还需要更新轴,而不仅仅是比例。为此,我在y比例中添加了一个类,以便在更新图表时轻松选择:
svg.select(".y")
.transition()
.call(d3.axisLeft(y).ticks(null, "s"))
.duration(500);