2017-12-06 4 views
0

사용자가 선택한 입력을 기반으로 d3의 막 대형 차트를 업데이트하려고합니다. 업데이트 된 데이터가 표시되고 있지만 이전 SVG 요소에 표시되고 있습니다. exit(). remove()를 사용해 보았지만 작동하지 않았습니다. 아래에 첨부 된 코드를 편집하여 이전 SVG 요소가 제거 될 수 있습니까? 여기 사용자 입력을 기반으로 d3의 막대 그래프 업데이트

<html> 
<head> 
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script> 
<style> 
.rect { 
    fill: steelblue; 
} 

.text { 
    fill: white; 
    font: 10px sans-serif; 
    text-anchor: middle; 
} 
</style> 
</head> 
<body> 
<select id = "variable"> 
        <option >select</option> 
        <option value="AZ">Arizona</option> 
        <option value="IL">Illinois</option> 
        <option value="NV">NV</option>   
</select> 
<script> 
var margin = {top: 20, right: 20, bottom: 70, left: 40}, 
     width = 500 - margin.left - margin.right, 
     height = 400 - margin.top - margin.bottom; 
var y = d3.scaleLinear() 
     .domain([0,5]) 
     .range([height, 0]); 
var yAxis = d3.axisLeft(y) 
       .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 + ")"); 
var bar; 

function update(state) 
{ 
d3.csv("test3.csv", function(error, data) 
    { 
      data = data.filter(function(d, i) 
           { 
            if (d['b_state'] == state) 
            { 
            return d; 
            } 
           }); 
      data = data.filter(function(d, i) 
           { 
            if (i<10) 
            { 
            return d; 
            } 
           }); 

      var barWidth = width/data.length; 

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

       bar = svg.selectAll("bar") 
          .data(data) 
          .enter() 
          .append("g") 
          .attr("transform", function(d, i) { return "translate(" + i * barWidth + ",0)"; }); 


       bar.append("rect") 
        .attr("y", function(d) { return y(d.b_stars); }) 
        .attr("height", function(d) { return height - y(d.b_stars); }) 
        .attr("width", barWidth - 1) 
        .attr("fill", "steelblue"); 

       bar.append("text") 
         .attr("x", function(d) { return height - y(d.b_stars); }) 
         .attr("y", -40) 
         .attr("dy", ".75em") 
         .text(function(d) { return d.b_name; }) 
         .attr("transform", "rotate(90)"); 
}); 
svg.exit().remove(); 
bar.exit().remove(); 
} 
d3.select("#variable")// selects the variable 
    .on("change", function() {// function that is called on changing 
    var variableName = document.getElementById("variable").value;// reads the variable value selected into another variable 
    update(variableName);}); 
</script> 
</body> 

답변

0

귀하의 문제는 bar 선택에 관한 것입니다. d3 설명서의이 부분을보실 수 있습니다 : Joining data.

bar = svg.selectAll("bar") 
    .data(data) 
    .enter() 

를 작성하여

당신은 그들에게 data에 합류, 모든 bar 요소를 선택하고,이 enter()와 함께, 당신은 bar 요소 (enter() documentation)에 연결되지 않은 모든 data 항목을 얻고있다. 그러나 bar 선택기는 아무 것도 일치하지 않습니다. select()/selectAll()의 매개 변수는 선택자 여야합니다 (요소, ., id는 # ...). 그래서 enter() 당신의 enter() 선택은 항상 새로운 요소를 업데이트하는 대신에 이전 요소 위에 생성합니다. 여기

bar = svg.selectAll(".bar") 
    .data(data) 
    .enter() 
    .append("g") 
    .attr('class', 'bar') 
    .attr("transform", function(d, i) { return "translate(" + i * barWidth + ",0)"; }); 

, 우리는 bar 클래스 모든 요소를 ​​선택하는 :

그래서 첫 번째 단계는이 선택하고 나중에이 선택을 일치 DOM 요소를 만들어을 다시 작성하는 것입니다. 항목에 연결된 DOM 요소가 data에서 없으므로 enter() 선택 항목에서 bar 클래스의 새 g으로 만듭니다.

다음과 같이 업데이트를 호출 할 때 selectAll('.bar')은 이전에 생성 된 g과 모두 일치하며 기존 요소에 enter() 항목을 적용하지 않습니다. 업데이트하거나 기존의 막대를 제거하려면

, 당신은 다음과 같이 코드를 작성할 수 있습니다

var barData = svg.selectAll(".bar") 
    .data(data) 

// Bars creation 
var barEnter = barData.enter() 
    .append("g") 
    .attr('class', 'bar') 
    .attr("transform", function(d, i) { return "translate(" + i * barWidth + ",0)"; }); 

barEnter.append("rect") 
    .attr("y", function(d) { return y(d.b_stars); }) 
    .attr("height", function(d) { return height - y(d.b_stars); }) 
    .attr("width", barWidth - 1) 
    .attr("fill", "steelblue"); 

barEnter.append("text") 
    .attr("x", function(d) { return height - y(d.b_stars); }) 
    .attr("y", -40) 
    .attr("dy", ".75em") 
    .text(function(d) { return d.b_name; }) 
    .attr("transform", "rotate(90)"); 


// Update the bar if the item in data is modified and already linked to a .bar element 
barData.select('rect') 
    .attr("height", function(d) { return height - y(d.b_stars); }) 

// Remove the DOM elements linked to data items which are not anymore in the data array 
barData.exit().remove() 
관련 문제