【问题标题】:d3js grouped bar chart toggling legendd3js分组条形图切换图例
【发布时间】:2018-03-21 14:24:46
【问题描述】:

我正在使用 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

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

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

【问题讨论】:

标签: javascript d3.js


【解决方案1】:

有几种方法可以解决这个问题。您可以轻松地使用进入/更新/退出周期,尽管与典型的周期使用相比,这有点复杂,因为嵌套元素和需要设置键以确保图表状态之间的平滑转换。

在这种情况下,简单地使用数组来保存要过滤掉的条形、隐藏这些条形、更新比例以不使用这些键的值并更新剩余的条形可能更​​容易。

这需要每个图例项都有一个 onclick 事件。点击时,在我们的 clicked 函数中,我们管理过滤掉的 (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

正如 cmets 中所述,您还需要更新轴,而不仅仅是比例。为此,我在 y 刻度中添加了一个类,以便在更新图表时轻松选择:

       svg.select(".y")
        .transition()
        .call(d3.axisLeft(y).ticks(null, "s"))
        .duration(500);

【讨论】:

  • 谢谢 Andrew - 这是另一种变体 - 是否有更好的方法 - 代码增强/清理可能 - 使用其中一个或其他 - 或混合? jsfiddle.net/shashank2104/xhgew00y/16
  • 干杯人 - 我已经把你的变成了一个 jsfiddle 来运行 json - jsfiddle.net/0ht35rpb/234
  • 嗨@Andrew Reid - 我有另一个类似的图表 - 折线图 - 我想拥有图例切换 - jsfiddle.net/xpb0hsey/28 stackoverflow.com/questions/46700389/…
  • @Andrew Reid 中可能存在错误 - “我没有看到 y 轴有任何变化,这不会导致图表的值错误吗?”
  • Yaxis 只有在删除具有最高值的系列时才会改变。今晚晚些时候我可以看一下,但是这周剩下的时间我只有手机。对我来说它改变了,你可以分享任何其他细节吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-31
  • 1970-01-01
  • 1970-01-01
  • 2019-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多