2015-02-04 5 views
0

이 문제 (d3 show labels only for ticks with data in a bar chart)의 순서에서 D3을 사용하여 누적 막 대형 차트의 데이터를 변경하기 위해 전환을 적용했습니다.막대가있는 d3 스택 막대가 전환시에 업데이트되지 않음

내 축은이 새 데이터 세트에 대해 완벽한 전환 및 수정을 수행하지만 수평 막대는 변경되지 않습니다. Lars (d3.js bar charts transitioning between multiple csv files)에서이 솔루션을 사용해 보았지만 막대가 변경된 것을 볼 수 있습니다.

내 코드 :

<!DOCTYPE html> 

<html xmlns="http://www.w3.org/1999/xhtml" class="ocks-org do-not-copy"> 
<head> 
    <link rel="stylesheet" type="text/css" href="style.css" /> 
</head> 
<body> 
<div><button class="btn btn-mini" id="backButton" onclick="updateData();">Update</button></div> 
<div id="timeLine"></div> 
<script src="http://d3js.org/d3.v3.min.js"></script> 
<script> 
var timeline; 

var margin = { 
    top : 20, 
    right : 10, 
    bottom : 60, 
    left : 80 
}, 
width = 500 - margin.left - margin.right, 
height = 500 - margin.top - margin.bottom; 

var x = d3.scale.linear() 
    .rangeRound([0, width]); 

var y = d3.scale.ordinal() 
    .rangeBands([height, 0], 0.1); 

var color = d3.scale.ordinal() 
    .range(["#1f77b4", "#2ca02c", "#E53524"]); 
//var color = d3.scale.category10() 

var xAxis = d3.svg.axis() 
    .scale(x) 
    .orient("bottom") 
    .tickFormat(d3.format(".2s")) 
    .ticks(10); 

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

timeline = d3.select("#timeLine").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 dataSet; 

dataSet = [{ 
     "Date" : "2014-01", 
     "insert" : "2", 
     "remove" : "17", 
     "updates" : "27" 
    }, { 
     "Date" : "2014-02", 
     "insert" : "27", 
     "remove" : "127", 
     "updates" : "47" 
    }, { 
     "Date" : "2014-03", 
     "insert" : "227", 
     "remove" : "17", 
     "updates" : "42" 
    }, { 
     "Date" : "2014-04", 
     "insert" : "0", 
     "remove" : "0", 
     "updates" : "0" 
    }, { 
     "Date" : "2014-05", 
     "insert" : "127", 
     "remove" : "1", 
     "updates" : "423" 
    }, 
]; 
color.domain(d3.keys(dataSet[0]).filter(function (key) { 
     return key !== "Date"; 
    })); 

dataSet.forEach(function (d) { 
    var x0 = 0; 
    d.ages = color.domain().map(function (name) { 
      return { 
       name : name, 
       x0 : x0, 
       x1 : x0 += +d[name] 
      }; 
     }); 
    d.total = d.ages[d.ages.length - 1].x1; 
}); 

yAxis.tickFormat(function (d) { 
    var val = 0; 
    dataSet.forEach(function (item) { 
     if (item.Date == d) 
      val = item.total; 
    }); 
    return val == 0 ? "" : d; 
}); 

y.domain(dataSet.map(function (d) { 
     return d.Date; 
    })); 

x.domain([0, d3.max(dataSet, function (d) { 
      return (d.total + 5); 
     })]); 

timeline.append("g") 
.attr("class", "x axis") 
.attr("transform", "translate(0," + height + ")") 
.call(xAxis) 
.append("text") 
.attr("x", 1) 
.attr("dx", "42em") 
.attr("dy", "3em") 
.style("text-anchor", "end") 
.text("Operations"); 

timeline.append("g") 
.attr("class", "y axis") 
.call(yAxis); 

var layer = timeline.selectAll(".state") 
    .data(dataSet) 
    .enter().append("g") 
    .attr("class", "rect") 
    .attr("transform", function (d) { 
     return "translate(0," + y(d.Date) + ")"; 
    }); 

var rect = layer.selectAll("rect") 
    .data(function (d) { 
     return d.ages; 
    }) 
    .enter().append("rect") 
    .attr("class", "rect") 
    .attr("width", 0) 
    .attr("x", width) 
    .attr('y', function (d, i) { 
     return y(d.Date); 
    }) 
    .attr("height", y.rangeBand()) 
    .style("fill", function (d) { 
     return color(d.name); 
    }); 

rect.transition() 
.duration(600) 
.delay(function (d, i) { 
    return i * 300; 
}) 
.attr("width", function (d) { 
    return x(d.x1) - x(d.x0); 
}) 
.attr("x", function (d) { 
    return x(d.x0); 
}); 

function updateData() { 

    dataSet = [{ 
     "Date" : "2014-11", 
     "insert" : "27", 
     "remove" : "1723", 
     "updates" : "7" 
    }, { 
     "Date" : "2014-12", 
     "insert" : "237", 
     "remove" : "12", 
     "updates" : "433" 
    }, { 
     "Date" : "2015-03", 
     "insert" : "22", 
     "remove" : "172", 
     "updates" : "423" 
    }, { 
     "Date" : "2015-05", 
     "insert" : "17", 
     "remove" : "122", 
     "updates" : "42" 
    }, { 
     "Date" : "2015-04", 
     "insert" : "0", 
     "remove" : "0", 
     "updates" : "0" 
    } 
]; 

dataSet.forEach(function (d) { 
    var x0 = 0; 
    d.ages = color.domain().map(function (name) { 
      return { 
       name : name, 
       x0 : x0, 
       x1 : x0 += +d[name] 
      }; 
     }); 
    d.total = d.ages[d.ages.length - 1].x1; 
}); 

yAxis.tickFormat(function (d) { 
    var val = 0; 
    dataSet.forEach(function (item) { 
     if (item.Date == d) 
      val = item.total; 
    }); 
    return val == 0 ? "" : d; 
}); 

y.domain(dataSet.map(function (d) { 
     return d.Date; 
    })); 

x.domain([0, d3.max(dataSet, function (d) { 
      return (d.total + 5); 
     })]); 

// Make the changes 
var transition = timeline.transition().duration(750), 
delay = function (d, i) { 
    return i * 50; 
}; 

// update bars 
//var teste = timeline.selectAll(".state").data(dataSet); 
var layer = timeline.selectAll(".state").data(dataSet).enter().append("g") 
    .attr("class", "rect") 
    .attr("transform", function (d) { 
     return "translate(0," + y(d.Date) + ")"; 
    }); 

var sel = layer.selectAll("rect") 
    .data(function (d) { 
     return d.ages; 
    }) 
    .enter().append("rect") 
    .attr("class", "rect") 
    .attr("width", 0) 
    .attr("x", width) 
    .attr('y', function (d, i) { 
     return y(d.Date); 
    }) 
    //.attr("height", y.rangeBand()) 
    .attr("height", y.rangeBand()) 
    .style("fill", function (d) { 
     return color(d.name); 
    }); 

//remove bars no longer present - DON'T WORK 
//sel.exit().remove(); 

sel.transition() 
.duration(600) 
.delay(function (d, i) { 
    return i * 300; 
}) 
.attr("x", function (d) { 
    return x(d.x0); 
}).attr("width", function (d) { 
    return x(d.x1) - x(d.x0); 
}) 
.attr('y', function (d, i) { 
    return y(d.Date); 
}) 
.attr("height", y.rangeBand()); 

transition.select(".y.axis") // change the y axis 
.call(yAxis); 

transition.select(".x.axis") // change the x axis 
.call(xAxis); 

} 
</script> 
</body> 
</html> 

감사합니다, 필리페

답변

0

는의 코드의 조직을 건너 보자. 주된 오류는 정의되지 않은 변수에 액세스하려고 시도하는 것입니다. 각 연결

var rect = layer.selectAll("rect") 
.data(function (d) { 
    return d.ages; 
}) 

는 "d.ages"의 값을 사각형, 그래서 당신은 "d.x0"와 "d.x1에 액세스 할 수는 스택 막대를 빌드 할 때 첫째, 당신은 그렇게 ". 업데이트 기능에서는 age 요소에 있기 때문에 존재하지 않는 "d.x0"과 "d.x1"에 직접 액세스하려고합니다.

주요 기능에 데이터 집합 항목 :

Object {name: "insert", x0: 0, x1: 2} 

업데이트 기능에서 데이터 집합 항목 : 시대에 다음

Object {Date: "2015-03", insert: "22", remove: "172", updates: "423", ages: Array[3]…} 

과 :

ages: Array[3] 
     0: Object 
     name: "insert" 
     x0: 0 
     x1: 22 
...................... 
+0

안녕 프란체스코, 감사에 대한 당신의 도움. 내 코드가 업데이트되었고 새 막대가 표시됩니다. 그러나 오래된 차트는 여전히 차트에 있습니다. sel.exit(). remove(); 내 업데이트 기능에서해야 할 일을하지 않습니다. – milheiros

+0

코드를 업데이트하면 그 코드를 살펴볼 수 있습니다. –

+0

function updateDate가 업데이트되었습니다. – milheiros