使用D3进行动态过滤

时间:2016-05-17 23:40:42

标签: d3.js

我对D3和编码很新。我试图设置一个条形图,其中包含/排除数据取决于复选框。我有一组产品组和国家/地区,我想要切换进/出酒吧所代表的总数。每个产品的输出应该是一个条。

我的完整数据集包含更多产品,产品组和国家/地区,因此为每个可能的复选框组合创建键值对是不可行的。相反,我想创建一个重新评估复选框并重新过滤数据的函数,并在复选框更改时更新汇总。

我不确定这个功能应该放在我的代码中的位置或它应该是什么样的......这就是我现在正在使用的内容:

  var data = data.filter(function(d) {
    if (document.getElementById("nz_button").checked) {
      return d.country == 'NZ'
    }
    if (document.getElementById("au_button").checked) {
      return d.country == 'AU'
    }
    if (document.getElementById("us_button").checked) {
      return d.country == 'US'
    }
  })


  // to see how many distinct groups there are and sum volume
  var products = d3.nest()
    .key(function(d) {
      return d.product
    })
    .rollup(function(leaves) {
      var sum = 0;
      leaves.forEach(function(d) {
        sum += d.volume;
      })
      return sum
    })
    .entries(data);

完整代码:http://plnkr.co/edit/qezdwMLt48RPc8KH17hS?p=preview

也许我应该选择并在需要时重新运行嵌套/汇总?

任何帮助表示赞赏。谢谢:))

1 个答案:

答案 0 :(得分:2)

您可以移动完整代码,使图形成为一个新函数,如下所示:

function makeDataGraph(data) {//function to make the graph.
      //
      // FILTER
      //
      var data = data.filter(function(d) {
        if (document.getElementById("au_button").checked) {
          return d.country == 'AU'
        }
        if (document.getElementById("us_button").checked) {
          return d.country == 'US'
        }
        if (document.getElementById("nz_button").checked) {
          return d.country == 'NZ'
        }

      })


      // to see how many distinct groups there are and sum volume
      var products = d3.nest()
        .key(function(d) {
          return d.product
        })
        .rollup(function(leaves) {
          var sum = 0;
          leaves.forEach(function(d) {
            sum += d.volume;
          })
          return sum
        })
        .entries(data);

      // sorting on descending total
      console.log(products);
      products.sort(function(a, b) {
        return b.values - a.values
      })

      var max = d3.max(products, function(d) {
        return d.values;
      });
      var xscale = d3.scale.linear()
        .domain([0, max])
        .range([0, 600])

      var svg = d3.select("svg");



      //
      // Still needs to be cleaned up  \/  \/
      //

      var rects = svg.selectAll("rect.product")
        .data(products)
      rects.exit().remove();  
      rects.enter().append("rect").classed("product", true)
      rects.attr({
        x: 200,
        y: function(d, i) {
          return 100 + i * 50
        },
        width: function(d, i) {
          return xscale(d.values)
        },
        height: 50
      }).on("click", function(d, i) {
        console.log(i, d);
      })


      var labels = svg.selectAll("text.label")
        .data(products)
      labels.exit().remove();
      labels.enter().append("text").classed("label", true)
      labels.attr({
        x: 195,
        y: function(d, i) {
          return 128 + i * 50
        },
        "text-anchor": "end",
        "alignment-baseline": "middle"
      }).text(function(d) {
        return d.key || "N/A"
      })


      var volume = svg.selectAll("text.volume")
        .data(products);
      volume.exit().remove();  
      volume.enter().append("text").classed("volume", true)
      volume.attr({
        x: function(d, i) {
          return 205 + xscale(d.values)
        },
        y: function(d, i) {
          return 128 + i * 50
        },
        "text-anchor": "start",
        "alignment-baseline": "middle"
      }).text(function(d) {
        return d.values || "N/A"
      })
    }

请务必执行rects.exit().remove();,以便在点击复选框更改数据时,会删除与旧数据相关的矩形。

现在你可以从click事件调用这个函数,也可以像这样加载tsv:

d3.tsv("data.tsv", function(err, udata) {

  var udata = udata.map(process);
  console.log("udata", udata);

  var data = udata // making new var to preserve unfiltered data
  makeDataGraph(data);//call the function to make graph

  function handleClick() { // event handler...
    makeDataGraph(data)
  }
  //add listener to all check boxes.
  d3.selectAll(".filter_button").on("click", handleClick);
});

工作代码here