2015-12-07 24 views
0

我有一個條形圖,可以從兩個下拉列表中選擇一個值 - 年份和類型。當我更改這些選項時,條形圖並不總是顯示正確的數據。我認爲我錯誤地過濾了,我想知道什麼是更好的方式去做這件事。謝謝!跟蹤兩個下拉列表中的值

Plunker is here.

代碼:

<!DOCTYPE html> 
    <meta charset="utf-8"> 
    <style> 
    body { font: 12px Arial;} 

    .bar { 
     fill: #0078a5; 
    } 

    .bar:hover { 
     fill: #18b7f2; 
    } 

    #tooltip { 
     position: absolute; 
     width: auto; 
     height: auto; 
     padding: 4px 6px; 
     background-color: #fff; 
     border:1px solid #eee; 
     -webkit-border-radius: 3px; 
     -moz-border-radius: 3px; 
     border-radius: 3px; 
     pointer-events: none; 
    } 

    #tooltip.hidden { 
     display: none; 
    } 

    #pop{ 
     background-color: #fff; 
     border:1px solid #eee; 
    } 

    #tooltip p { 
     margin: 0; 
     font-family: sans-serif; 
     font-size: 14px; 
    } 

    .axis { 
     font: 10px sans-serif; 
    } 

    .axis path, 
    .axis line { 
     fill: none; 
     stroke: #000; 
     shape-rendering: crispEdges; 
    } 

    .x.axis path { 
     display: none; 
    } 

    #legendContainer{ 
     position:absolute; 
     top:85px; 
     left:10px; 
     overflow: auto; 
     height:360px; 
     width:120px; 
     font-family:Helvetica, Arial, sans-serif; 
     font-size:11px; 
    } 
    #legend{ 
     width:100px; 
     height:200px; 
    } 
    .legend { 
     font-size: 12px; 
     font-weight: normal; 
     text-anchor: left; 
      cursor: pointer; 
    } 
    #bar{ 
     background:#ccc; 
     color:#222; 
     padding:8px 15px; 
     margin-right:6px; 
     border-radius:5px; 
     float:left; 
     width:20px; 
    } 
    .active{ 
     background:#0b3774 !important; 
     color:#fff !important; 
    } 
    </style> 
    <body> 
    <script src="http://d3js.org/d3.v3.min.js"></script> 
    <script src="//code.jquery.com/jquery-1.10.2.js"></script> 
    <label for="years">Year: </label> 
    <select id="years"> 
     <option value="1900">1900</option> 
     <option value="1950">1950</option> 
     <option value="2000">2000</option> 
     <option value="2015" selected="selected">2015</option> 
    </select> 
    <label for="inds">Type: </label> 
    <select id="inds"> 
      <option value="apples">apples</option> 
      <option value="pears">pears</option> 
      <option value="tomatoes">tomatoes</option> 
    </select> 
    <div id="legendContainer" class="legendContainer"> 
     <svg id="legend"></svg> 
    </div> 
    <div id="tooltip" class="hidden"> 
     <p><span id="state"></span></p> 
    </div> 

    <script> 

    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 myYear = d3.select("#years").node().value; 
     var myInd = d3.select("#inds").node().value; 

     console.log("myYear: ", myYear); 
     console.log("myInd: ", myInd); 

     d3.select('#years') 
       .on("change", function() {  
        var timeo = document.getElementById("years"); 
        var yearo = timeo.options[timeo.selectedIndex].value; 

        data = filterJSON(json, 'year', yearo); 
        updateGraph(data); 

       }); 

     d3.select('#inds') 
       .on("change", function() {  
        var sect = document.getElementById("inds"); 
        var section = sect.options[sect.selectedIndex].value; 

        data = filterJSON(json, 'produce', section); 
        updateGraph(data); 
     }); 

     // initial graph/defaults  
    var pop = filterJSON(json, 'year', "2015"); 
    var data = filterJSON(pop, 'produce', 'apples'); 
    updateGraph(data); 

    }); 

    function updateGraph(data) { 
     // data.sort(function(a,b) {return b.state-a.state;}); 
     data.forEach(function(d) { 
      d.active = true; 
     }); 

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

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

     var color = d3.scale.category20b(); 

     var bars = svg.selectAll(".bar") 
      .data(data); 

     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() + 100; 
        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); 
       }) 
       .on("click", function(d){ 
        d3.select(this).style("fill", "#ff3300"); 
       }); 

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

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



     var legend = d3.select("#legend") 
        .selectAll("text") 
        .data(data); 

        legend.enter().append("text") 
        .attr("x", 0) 
        .attr("y", function(d,i){return 10 +i*15;}) 
        .attr("class", "legend") 
         .style("fill", "#0078a5") 
         .on("click", function(d){ 
        // Determine if current line is visible 
        d.active = !d.active; 
        // Hide or show the elements based on the ID 
        d3.select("#tag"+d.state.replace(/\s+/g, '')) 
          .transition() 
          .duration(100) 
          .style("fill", "#ff3300"); 

          var xPosition = parseFloat(d3.select(this).attr("x")) + x.rangeBand() + 100; 
          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.year + ": " + d.value); 
          d3.select("#tooltip").classed("hidden", false); 
         }); 

        legend.transition() 
         .text(function(d){return d.state;}); 

        legend.exit().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"); 
    }; 

    </script> 

數據:

[ 
    { 
     "state":"Maine", 
     "produce":"apples", 
     "year":1900, 
     "value":"131" 
    }, 
    { 
     "state":"Maine", 
     "produce":"apples", 
     "year":1950, 
     "value":"231" 
    }, 
    { 
     "state":"Maine", 
     "produce":"apples", 
     "year":2000, 
     "value":"191" 
    }, 
    { 
     "state":"Maine", 
     "produce":"apples", 
     "year":2015, 
     "value":"302" 
    }, 
    { 
     "state":"Pennsylvania", 
     "produce":"apples", 
     "year":1900, 
     "value":"31" 
    }, 
    { 
     "state":"Pennsylvania", 
     "produce":"apples", 
     "year":1950, 
     "value":"331" 
    }, 
    { 
     "state":"Pennsylvania", 
     "produce":"apples", 
     "year":2000, 
     "value":"291" 
    }, 
    { 
     "state":"Pennsylvania", 
     "produce":"apples", 
     "year":2015, 
     "value":"250" 
    }, 
    { 
     "state":"Ohio", 
     "produce":"apples", 
     "year":1900, 
     "value":"11" 
    }, 
    { 
     "state":"Ohio", 
     "produce":"apples", 
     "year":1950, 
     "value":"230" 
    }, 
    { 
     "state":"Ohio", 
     "produce":"apples", 
     "year":2000, 
     "value":"185" 
    }, 
    { 
     "state":"Ohio", 
     "produce":"apples", 
     "year":2015, 
     "value":"310" 
    }, 
    { 
     "state":"Maine", 
     "produce":"pears", 
     "year":1900, 
     "value":"171" 
    }, 
    { 
     "state":"Maine", 
     "produce":"pears", 
     "year":1950, 
     "value":"121" 
    }, 
    { 
     "state":"Maine", 
     "produce":"pears", 
     "year":2000, 
     "value":"231" 
    }, 
    { 
     "state":"Maine", 
     "produce":"pears", 
     "year":2015, 
     "value":"202" 
    }, 
    { 
     "state":"Pennsylvania", 
     "produce":"pears", 
     "year":1900, 
     "value":"73" 
    }, 
    { 
     "state":"Pennsylvania", 
     "produce":"pears", 
     "year":1950, 
     "value":"151" 
    }, 
    { 
     "state":"Pennsylvania", 
     "produce":"pears", 
     "year":2000, 
     "value":"399" 
    }, 
    { 
     "state":"Pennsylvania", 
     "produce":"pears", 
     "year":2015, 
     "value":"140" 
    }, 
    { 
     "state":"Ohio", 
     "produce":"pears", 
     "year":1900, 
     "value":"146" 
    }, 
    { 
     "state":"Ohio", 
     "produce":"pears", 
     "year":1950, 
     "value":"130" 
    }, 
    { 
     "state":"Ohio", 
     "produce":"pears", 
     "year":2000, 
     "value":"195" 
    }, 
    { 
     "state":"Ohio", 
     "produce":"pears", 
     "year":2015, 
     "value":"210" 
    }, 
    { 
     "state":"Maine", 
     "produce":"tomatoes", 
     "year":1900, 
     "value":"71" 
    }, 
    { 
     "state":"Maine", 
     "produce":"tomatoes", 
     "year":1950, 
     "value":"221" 
    }, 
    { 
     "state":"Maine", 
     "produce":"tomatoes", 
     "year":2000, 
     "value":"31" 
    }, 
    { 
     "state":"Maine", 
     "produce":"tomatoes", 
     "year":2015, 
     "value":"102" 
    }, 
    { 
     "state":"Pennsylvania", 
     "produce":"tomatoes", 
     "year":1900, 
     "value":"173" 
    }, 
    { 
     "state":"Pennsylvania", 
     "produce":"tomatoes", 
     "year":1950, 
     "value":"194" 
    }, 
    { 
     "state":"Pennsylvania", 
     "produce":"tomatoes", 
     "year":2000, 
     "value":"195" 
    }, 
    { 
     "state":"Pennsylvania", 
     "produce":"tomatoes", 
     "year":2015, 
     "value":"230" 
    }, 
    { 
     "state":"Ohio", 
     "produce":"tomatoes", 
     "year":1900, 
     "value":"216" 
    }, 
    { 
     "state":"Ohio", 
     "produce":"tomatoes", 
     "year":1950, 
     "value":"184" 
    }, 
    { 
     "state":"Ohio", 
     "produce":"tomatoes", 
     "year":2000, 
     "value":"125" 
    }, 
    { 
     "state":"Ohio", 
     "produce":"tomatoes", 
     "year":2015, 
     "value":"150" 
    } 
    ] 

回答

1

您可以使用過濾器,而不是爲每個屬性和兩個循環合併到一個這樣的:

function doFilter(data){ 
    return data.filter(function(d){return d.year == d3.select('#years').node().value && d.produce == d3.select('#inds').node().value}); 
} 

    //onchange of years 
    d3.select('#years') 
      .on("change", function() {  
       var data1 = doFilter(json) 
       updateGraph(data1); 
      }); 
    //onchange of inds    
    d3.select('#inds') 
      .on("change", function() {  
       var data1 = doFilter(json) 
       updateGraph(data1); 
    }); 

var data1 = doFilter(json)    
    // initial graph/defaults  
updateGraph(data1); 

工作代碼here

希望這會有所幫助!

+0

這是完美的。非常感謝你的幫助! – sprucegoose

相關問題