d3.js条形图 - 在图例点击时显示/隐藏栏。如何正确过滤?

时间:2016-03-14 05:22:13

标签: javascript jquery d3.js

我的条形图会根据下拉选项而变化。下拉选项过滤我的数据文件。

然后,当单击相应的图例项目时,我显示/隐藏图表中的条形图。表演/隐藏正在发挥作用。问题是年份数据没有被正确过滤。单击图例项时,将忽略从下拉列表中选择年份时发生的数据过滤。我不确定为什么。

如何解决这个问题?

我的代码如下,这是一个Plunker:https://plnkr.co/edit/gMa09b2jO9shxCbXDaFD?p=preview

HTML:

<!DOCTYPE html>
    <meta charset="utf-8">
    <link rel="stylesheet" type="text/css" href="style.css">

    <body>
    <script src="https://d3js.org/d3.v3.min.js"></script>
    <script src="//code.jquery.com/jquery-1.10.2.js"></script>
    <div id="dropdown">
    <div class="ccms_form_element cfdiv_custom" id="indSelectors">
    <label>Dimension:</label>
    <select size="1" id="dimensions" class=" validate['required']" title="" type="select" name="style">
    <option value="">-Select-</option>
    <option value="Fruit">Fruit</option>
    <option value="Vegetables">Vegetables</option>
    </select>
    <div class="clear"></div>
    <div id="error-message-style"></div>
    </div>
    <div id="secondaryDrop">
      <div id="Fruit"  class="style-sub-1"  style="display: none;" name="stylesub1">
        <label>Fruit</label>
          <select class="inds">
            <option value="">- Select -</option>
            <option value="apples">apples</option>
            <option value="pears">pears</option>
          </select>
      </div>
      <div id="Vegetables"  class="style-sub-1"  style="display: none;" name="stylesub1">
        <label>Vegetables</label>
          <select class="inds">
            <option value="">- Select -</option>
            <option value="tomatoes">tomatoes</option>
        </select>
      </div>
    </div>
    <div class="clear"></div>
    <div id="error-message-style-sub-1"></div>
    </div>
    <div id="tertiaryDrop">
      <div id="apples"  class="style-sub-2"  style="display: none;" name="stylesub2">
        <label>Year</label>
          <select class="years">
            <option value="">- Select a Year -</option>
            <option value="1950">1950</option>
            <option value="2000">2000</option>
          </select>
      </div>
      <div id="pears"  class="style-sub-2"  style="display: none;" name="stylesub2">
        <label>Year</label>
          <select class="years">
            <option value="">- Select a Year -</option>
            <option value="1900">1900</option>
            <option value="2015">2015</option>
          </select>
      </div>
      <div id="tomatoes"  class="style-sub-2"  style="display: none;" name="stylesub2">
        <label>Year</label>
          <select class="years">
            <option value="">- Select a Year -</option>
            <option value="2000">2000</option>
            <option value="2015">2015</option>
          </select>
      </div>
      <div class="clear"></div>
      <div id="error-message-style-sub-2"></div>
    </div>
    </div>
    <div id="legendContainer" class="legendContainer">
      <svg id="legend"></svg>
    </div>
    <div id="tooltip" class="hidden">
      <p><span id="state"></span></p>
    </div>

    <script src="script.js"></script>

JS:

$("#dimensions").change ( function () {
        var targID  = $(this).val ();
        $("div.style-sub-1").hide ();
        $('#' + targID).show ();
    } );

    $(".inds").change ( function () {
        var targID  = $(this).val ();
        $("div.style-sub-2").hide ();
        $('#' + targID).show ();
    } );

    function filterJSON(json, key, value) {
      var result = [];
      for (var foo in json) {
        if (json[foo][key] === value) {
          result.push(json[foo]);
        }
      }
      return result;
    }

    var margin = {top: 20, right: 20, bottom: 130, left: 160},
        width = 1200 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom,
        padding = 0.25;

    var x = d3.scale.ordinal()
        .rangeRoundBands([0, width - margin.left - margin.right], padding);

    var y = d3.scale.linear()
        .range([height, 0]);

    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left")
        .ticks(10);

    var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
      .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    d3.json("data.json", function(error, json) {
        if (error) throw error;

        json.forEach(function(d) {
            d.year = +d.year;
            d.value = +d.value;
        });

    var yr;

        $('.inds')
                .on("change", function () {

                    var prod = $(this).val();
              console.log("prod:", prod);

                    data = filterJSON(json, 'produce', prod);

              console.log("data: ", data);
              updateGraph(data);


                    $('.years')
                            .on("change", function () {

                                var yr = $(this).val();
                          yr = +yr;

                                data1 = filterJSON(data, 'year', yr);

                          updateGraph(data1, yr);
                            });

        });

    // data = filterJSON(json, 'produce', 'apples');
    // data1 = filterJSON(data, 'year', 2015);
    // updateGraph(data1);

    });

    function updateGraph(data1, yr) {
      console.log("year: ", yr);

      console.log("data1: ", data1);

      data1.sort(function(a,b) {return a.value-b.value;});

      x.domain(data1.map(function(d) { return d.state; }));
      y.domain([0, d3.max(data1, function(d) { return d.value; })]);

      var result = data1.filter(function(d){
                      return $("." + d.state.replace(/\s|\(|\)|\'|\,+/g, '')).attr("fill") != "#cccccc"
                      // matching the data with selector status
                    })
      console.log("result: ", result);

      var bars = svg.selectAll(".bar")
          .data(result, function(d){return d.state.replace(/\s|\(|\)|\'|\,+/g, '')});

        bars.enter().append("rect")
          .attr("class", "bar")
          .on("mouseover", function(d) {
                    //Get this bar's x/y values, then augment for the tooltip
                    var xPosition = parseFloat(d3.select(this).attr("x")) + x.rangeBand() + 5;
                    var yPosition = parseFloat(d3.select(this).attr("y")) / 2 + height / 2;
                    //Update the tooltip position and value
                    d3.select("#tooltip")
                        .style("left", xPosition + "px")
                        .style("top", yPosition + "px")
                        .select("#state")
                        .text(d.state + ": " + d.produce + ": " + d.year + ": " + d.value);
                    d3.select("#tooltip").classed("hidden", false);
              })
              .on("mouseout", function() {
                    d3.select("#tooltip").classed("hidden", true);
              });

      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();

      // LEGEND GROUPS
      var legendGroups = d3.select("#legend")
        .selectAll(".legendGroup")
        .data(data1, function(d){
          return d.state; // always try and use a key function to uniquely identify
        });

      var enterGroups = legendGroups
        .enter()
        .append("g")
        .attr("class","legendGroup");

      legendGroups
        .exit()
        .remove();

      legendGroups
        .attr("transform",function(d,i){
           return "translate(10," + (10 + i* 15) + ")"; // position the whole group
         });

      enterGroups.append("text")
        .text(function(d){return d.state;})
        .attr("x", 15)
        .attr("y", 10);

      enterGroups
        .append("rect")
        .attr("width", 10)
        .attr("height", 10)
        .attr("fill",function(d) {
            return "#0000ff";
        })
        .attr("class", function(d,i){return "legendcheckbox " + d.state.replace(/\s|\(|\)|\'|\,|\.+/g, '')})
        .on("click", function(d){
              d.active = !d.active;
              d3.select(this).attr("fill", function(d){
                if(d3.select(this).attr("fill")  == "#cccccc"){
                  return "#0000ff";
                }else {
                  return "#cccccc";
                }
              })


            var result = data1.filter(function(d, yr){
                          return $("." + d.state.replace(/\s|\(|\)|\'|\,+/g, '')).attr("fill") != "#cccccc"
                        })
                  console.log("data1 after legend click", data1);
                  console.log("result after legend click: ", result);

            x.domain(result.map(function(d) { return d.state; }));
            y.domain([0, d3.max(result, function(d) { return d.value; })]);

            svg.select(".x.axis")
              .transition()
              .call(xAxis);

           svg.selectAll(".bar")
             .data(result, function(d){return d.state.replace(/\s|\(|\)|\'|\,|\.+/g, '')})
             .enter()
             .append("rect")
             .attr("class", "bar")
             .on("mouseover", function(d) {
               var xPosition = parseFloat(d3.select(this).attr("x")) + x.rangeBand() + 5;
               var yPosition = parseFloat(d3.select(this).attr("y")) / 2 + height / 2;
               d3.select("#tooltip")
                 .style("left", xPosition + "px")
                 .style("top", yPosition + "px")
                 .select("#state")
                 .text(d.state + ": " + d.produce + ": " + d.year + ": " + d.value);
               d3.select("#tooltip").classed("hidden", false);
             })
             .on("mouseout", function() {
               d3.select("#tooltip").classed("hidden", true);
             });

          svg.selectAll(".bar")
            .transition()
            .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); });

          svg.selectAll(".bar").data(result, function(d){return d.state.replace(/\s|\(|\)|\'|\,|\.+/g, '')}).exit().remove()

        }); // end on click

        svg.selectAll(".axis").remove();



      svg.append("g")
          .attr("class", "y axis")
          .call(yAxis)
        .append("text")
          .attr("transform", "rotate(-90)")
          .attr("y", 6)
          .attr("dy", ".71em")
          .style("text-anchor", "end")
          .text("value");
    };

数据(.json文件)遵循以下格式:

    [{
      "state":"Maine",
      "produce":"apples",
      "year":1900,
      "value":"131"
    },
    {
      "state":"Maine",
      "produce":"apples",
      "year":1950,
      "value":"231"
    },
    {
      "state":"Maine",
      "produce":"apples",
      "year":2000,
      "value":"191"
    }...

可以在Plunker中看到完整的数据文件。

1 个答案:

答案 0 :(得分:1)

我制作了一个全局变量required_unless

currentData

然后在图例中点击对currentData进行过滤:

var currentData = [];

//set the currentData in the update
function updateGraph(data1, yr) {
  currentData = data1;

工作代码here