4
D3.js를 사용하여 동적으로 누적 막대 차트를 플롯하려고합니다. 기본 요구 사항은 몇 초마다 새로운 데이터 포인트가 생기고 스택 차트를 다시 채울 수 있어야한다는 것입니다. 이것은 내가 작성한 코드입니다.D3의 동적 스택 막대 차트
<html>
<head>
<title>Page Title</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="d3/d3.js"></script>
<script src="d3/d3.csv.js"></script>
<script src="d3/d3.layout.js"></script>
</head>
<body>
<style type="text/css">
.chart rect {
stroke: white;
}
</style>
<script>
var t = 1297110663, // start time (seconds since epoch)
v = 70, // start value (subscribers)
sentidata = d3.range(33).map(next); // starting dataset
var w = 20,
h = 80;
var x = d3.scale.linear()
.domain([0, 1])
.range([0, w]);
var y = d3.scale.linear()
.domain([0, 200])
.rangeRound([0, h]);
var z = d3.scale.ordinal()
.range(["lightpink", "darkgray"]);
//This function creates random test data of format : time, posvalue, negvalue
function next() {
return {
time: ++t,
posvalue: v = ~~Math.max(10, Math.min(90, v + 10 * (Math.random() - .5))),
negvalue: v = ~~Math.max(10, Math.min(90, v + 10 * (Math.random() - .5)))
};
}
//This function readjusts the data with one new data point and calls redraw function to replot the graph
setInterval(function() {
sentidata.shift();
sentidata.push(next());
redraw(sentidata);
}, 1500);
var svg = d3.select("body").append("svg:svg")
.attr("class", "chart")
.attr("width", w * sentidata.length - 1)
.attr("height", h);
//Transpose the data into layers by Sentiment
var sent = d3.layout.stack()(["posvalue","negvalue"].map(function(sentiment){
return sentidata.map(function(d){
return {x:d.time, y:+d[sentiment]};
});
}));
//Add a group for each Sentiment
var sentiment = svg.selectAll("g.sentiment")
.data(sent)
.enter()
.append("svg:g")
.attr("class","sentiment")
.style("fill", function(d,i){return z(i);})
.style("stroke", function(d,i){return d3.rgb(z(i)).darker();});
//Add a rectangle for each time value
var rect = sentiment.selectAll("rect")
.data(Object)
.enter()
.append("svg:rect")
.attr("x",function(d, i) { return x(i) - .5; })
.attr("y",function(d){return h - y(d.y0)-y(d.y);})
.attr("height", function(d){return y(d.y);})
.attr("width",w);
svg.append("line")
.attr("x1", 0)
.attr("x2", w * sentidata.length)
.attr("y1", h - .5)
.attr("y2", h - .5)
.style("stroke", "#000");
function redraw(data) {
//Transpose the data into layers by Sentiment
var sent = d3.layout.stack()(["posvalue","negvalue"].map(function(sentiment){
return data.map(function(d){
return {x:d.time, y:+d[sentiment]};
});
}));
//Add a group for each Sentiment
var sentiment = svg.selectAll("g.sentiment")
.data(sent)
.transition()
.duration(1000)
.attr("class","sentiment")
.style("fill", function(d,i){return z(i);})
.style("stroke", function(d,i){return d3.rgb(z(i)).darker();});
var rect = sentiment.selectAll("rect")
.data(Object)
.transition()
.duration(1000)
.attr("y",function(d){return h - y(d.y0)-y(d.y);})
.attr("height", function(d){return y(d.y);});
}
</script>
</body>
</html>
초기 누적 차트가 잘 표시됩니다. 하지만 다시 그리기 메서드를 호출하면 나에게 "[object Object]에 메서드 'data'가 없습니다."오류가 발생합니다. 이 오류는 rect 변수를 초기화하려고 할 때 발생합니다.
var rect = sentiment.selectAll("rect")
.data(Object)
내가 잘못하고 있는지 확실하지 않습니다. 내가 뭔가를 찾고 있는데 similar
정말 감사하겠습니다!
.DATA '()'플롯 사용하기위한 값 또는 객체 배열 걸린다. "Object"를 전달하는 대신 표시 할 데이터를 전달하십시오. –
알았어요. selectAll을 호출 한 직후에 전환을 생성하기 위해 체인 체이닝을 사용했기 때문에, 다시 그리기에서 전환으로 'var sentiment'를 정의했습니다. 따라서 오류 메시지 이 암시 적으로 표시되므로 데이터 메서드가 없습니다. 그래서 충돌을 피하기 위해 별도의 명세서 으로 전환을 만들었습니다. D3 Google 그룹스에서 너무 빠르게 반응 한 Mike Bostoc에게 감사드립니다. –