2017-04-13 77 views

回答

1

您應該按照添加數據添加每個元素的模式。這樣你總是有一個update,enterexit的選擇。除去exit和增加新的元素enter後,您可以合併updateenter和更新的屬性:

Here is the updated block

//define some data 
var data = [ 
     {"location": 1, "month": "Jan", "year": 2017, "value": "#ccc"}, 
     {"location": 2, "month": "Jan", "year": 2017, "value": "#999"}, 
     {"location": 3, "month": "Jan", "year": 2017, "value": "#666"}, 
     {"location": 4, "month": "Jan", "year": 2017, "value": "#333"}, 
     {"location": 1, "month": "Jan", "year": 2018, "value": "#fcc"}, 
     {"location": 2, "month": "Jan", "year": 2018, "value": "#f99"}, 
     {"location": 3, "month": "Jan", "year": 2018, "value": "#f66"}, 
    {"location": 4, "month": "Jan", "year": 2018, "value": "#f33"}, 
     {"location": 1, "month": "Feb", "year": 2017, "value": "#cfc"}, 
     {"location": 2, "month": "Feb", "year": 2017, "value": "#9f9"}, 
     {"location": 3, "month": "Feb", "year": 2017, "value": "#6f6"}, 
     {"location": 4, "month": "Feb", "year": 2017, "value": "#3f3"}, 
     {"location": 1, "month": "Feb", "year": 2018, "value": "#ccf"}, 
     {"location": 2, "month": "Feb", "year": 2018, "value": "#99f"}, 
     {"location": 3, "month": "Feb", "year": 2018, "value": "#66f"}, 
     {"location": 4, "month": "Feb", "year": 2018, "value": "#33f"}, 
    {"location": 5, "month": "Feb", "year": 2018, "value": "#0505ff"}, 
    ] 

// nest the data by month then year 
var by_month = d3.nest() 
     .key(function(d){return d.month}) 
     .key(function(d){return d.year}) 
     .entries(data) 


function render(ident, key_month) { 

    var w = 500 
    var h = 100 

    var container = d3.select(ident) 

    // select and add a container div for each year in the data 
    // using only the data for the target month 
    var year = container 
     .selectAll("div.year") 

    var data = by_month.filter(function(d){return d.key == key_month})[0].values; 
    var yearAll= year.data(data); 


    yearAll.exit().remove(); 


    var yearEnter= yearAll 
     .enter() 
    .append("div") 
    .classed("year",true); 

    //Add h2 and svg 
    yearEnter.append("h2"); 
    yearEnter.append("svg") 
        .append("g") 
        .classed("gwrapper",true); 

    yearEnter = yearEnter.merge(yearAll); 

    yearEnter.select("h2") 
    .text(function(d) {return d.values[0].month + " " + d.values[0].year ;}); 

    // update the svg dimensions 
    yearEnter.select("svg") 
    .attr("width", w) 
     .attr("height", h); 


    // select and add element g location 
    var gloc = yearEnter.select(".gwrapper").selectAll("g") 
              .data(function(d){return d.values;}); 

    gloc.exit().remove(); 


    var glocEnter = gloc.enter() 
             .append("g") 
         .classed("loc",true); 

    glocEnter.append("rect"); 
      ; 

    glocEnter = glocEnter.merge(gloc); 


    // merge and position element wrappers 
    glocEnter 
     .attr("transform", function(d,i){return "translate("+[w/5*i]+")"}); 

    var t = d3.transition().duration(1000); 

    glocEnter.select("rect") 
      .attr("x", (w/5 - 5)/2) 
           .attr("y", (w/5 - 5)/2) 
           .attr("width", 0) 
            .attr("height", 0) 
           .attr("fill", "black") 
           .transition(t) 
           .attr("x", 5) 
           .attr("y", 0) 
            .attr("width", w/5 - 5) 
            .attr("height", w/5 - 5) 
           .attr("fill", function(d){return d.value}); 

} 

// on button click change the subset of data being used 
d3.selectAll(".month").on("click", function(){ 
    render("#toggle",this.getAttribute("data-month")) 
}) 


d3.selectAll("#clearb").on("click", function(){ 
    d3.selectAll("g.loc").remove(); 
}) 

render("#toggle","Jan") 
+0

感謝這個,它的偉大工程。雖然如果這是它應該完成的方式,我不太明白這裏的第二個示例如何工作https://github.com/d3/d3-selection/issues/86#issuecomment-289087950而不重新綁定數據 – Yanofsky

+0

@ Yanofsky根據Mike Bostock的消息,我已經更新了答案。 – Marcelo