2016-03-14 88 views
2

我有一個條形圖,根據下拉選擇而變化。下拉選擇過濾我的數據文件。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中看到。在傳說中點擊

var currentData = []; 

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

然後做CURRENTDATA過濾:

回答

1

我做了一個全局變量currentData

var result = currentData.filter(function(d, yr){ 
         return $("." + d.state.replace(/\s|\(|\)|\'|\,+/g, '')).attr("fill") != "#cccccc" 
        }) 

工作代碼here

+0

真棒,精美的作品。非常感謝您的幫助! – sprucegoose