d3js分组条形图切换传奇

时间:2017-10-10 08:46:39

标签: javascript d3.js

我正在使用d3.js渲染一个分组的条形图,我希望在点击图例时动画转换条形图(显示/隐藏不同的系列)。

从此。

enter image description here 到这个

enter image description here

也许还会改变比例

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

https://plnkr.co/edit/JUaLXmeCvHh0zUmrKClQ?p=preview

http://jsfiddle.net/ramseyfeng/8790t2vk/

1 个答案:

答案 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);