2017-02-25 2 views
1

'참석자'와 '동전'이있는 막 대형 차트를 만들려고합니다. 외부 파일에서 데이터를 읽는 중이고 데이터가 변경되면 차트를 업데이트하고 싶습니다 (또는 몇 초마다 파일을 확인하고 데이터를 업데이트하십시오). 나는 일반적인 업데이트 패턴에 대해 mbostock's 튜토리얼을 따라 가려고 노력해 왔지만, 내 자신의 차트에 적응하기 시작한 지옥이 있었다. 외부 파일에서 전환 데이터를 처리하는 다른 질문/답변을 찾지 못했습니다. 그러나 내가 놓친 것이 있으면 알려주십시오. 그래서, 나는 너를 모두 돌린다! 나는이 정말 D3와 깊이 파고하려고 처음 언급해야D3 - 외부 파일에서 업데이트 된 데이터를 읽은 후 전환

var margin = {top: 40, right: 20, bottom: 30, left: 40}, 
width = 950 - margin.left - margin.right, 
height = 500 - margin.top - margin.bottom; 

var formatNumber = d3.format(".1f"); 

var x = d3.scale.ordinal() 
.rangeRoundBands([0, width], .1); 

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") 
.tickFormat(formatNumber); 

var tip = d3.tip() 
.attr('class', 'd3-tip') 
.offset([-10, 0]) 
.html(function(d) { 

return "<strong>Coins:</strong> <span style='color:red'>" + d.coins + "</span>"; 
}) 

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 + ")"); 

svg.call(tip); 

d3.tsv("data.tsv", type, function(error, data) { 
x.domain(data.map(function(d) { return d.attendee; })); 
y.domain([0, d3.max(data, function(d) { return d.coins; })]); 

svg.append("g") 
    .attr("class", "x axis") 
    .attr("transform", "translate(0," + height + ")") 
    .call(xAxis); 

svg.append("g") 
    .attr("class", "y axis") 
    .call(yAxis) 
.append("text") 
    .attr("transform", "rotate(-90)") 
    .attr("y", 6) 
    .attr("dy", ".5em") 
    .style("text-anchor", "end") 
    .text("Coins"); 

svg.selectAll(".bar") 
    .data(data) 
.enter().append("rect") 
    .attr("class", "bar") 
    .attr("x", function(d) { return x(d.attendee); }) 
    .attr("width", x.rangeBand()) 
    .attr("y", function(d) { return y(d.coins); }) 
    .attr("height", function(d) { return height - y(d.coins); }) 
    .on('mouseover', tip.show) 
    .on('mouseout', tip.hide) 
}); 

function type(d) { 
    d.coins = +d.coins; 
    return d; 
} 

var inter = setInterval(function() { 
update(); 
}, 1000); 

function update() { 

} 

:

여기에 내 현재 JS 코드입니다. 나는 너무 분명한 것을 놓치지 않기를 바란다! 어떤 도움, 제안, 또는 올바른 방향으로 밀고 주셔서 미리 감사드립니다!

** 막대 차트가 편집 된 샘플에 기능을 추가하려는 시도임을 알리기 위해 편집하십시오. here.

편집 2 : 더 나은 형식 여기 .tsv 형식을 추가 : 모든

attendee coins 
George 35 
Charlie 50 
Harrison 50 
Billy 45 
Wally 30 
Harley 40 
Steven 120 
Paul 30 
+0

이봐, 당신이 조금 그래서 우리는 그것을 테스트 할 수 TSV 공유 할 수 있습니다

function renderBar(rect) { rect.attr("class", "bar") .attr("x", function(d) { return x(d.attendee); }) .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.coins); }) .attr("height", function(d) { return height - y(d.coins); }); } 

이 plunkr 내가 d3.tip 부분을 제거, 작업 코드를 보여줍니다? – torresomar

+0

@torresomar 더 나은 서식 지정을위한 주된 질문에 추가되었습니다! – gpwilson

답변

1

먼저 다음과 같이 업데이트 함수를 호출 할 수 있습니다 :

var inter = setInterval(updateChart, 5000); 

(가) 가져 시뮬레이션 할 논리를가한다 다음 :

function fetchData() { 
    console.log('fetching'); 
    return new Promise(function(resolve, reject) { 
    var data = [{ 
     attendee: "Paul", 
     coins: Math.floor(Math.random() * 40) + 1 
    }, { 
     attendee: "Bessy the Cow", 
     coins: Math.floor(Math.random() * 40) + 1 
    }, { 
     attendee: "Zeke", 
     coins: Math.floor(Math.random() * 40) + 1 
    }]; 
    setTimeout(function() { // Adding timeout to simulate latency 
     resolve(data); 
    }, 4000) 
    }) 
} 

그런 다음 새로 검색된 데이터 :

function updateChart() { 
    fetchData() 
    .then(function(data) { 
     // Update our y domain with new coin values 
     y.domain([0, d3.max(data, function(d) { 
     return d.coins; 
     })]); 
     // Update our axis because our y domain just changed 
     svg.select('g.y') 
     .transition() 
     .duration(300) 
     .ease("linear") 
     .call(yAxis); 
     // Create a new data join with the simuldated data 
     var bars = svg.selectAll('.bar').data(data); 
     // Remove extra elements (say new data just has 2 bars, this would remove third one) 
     bars.exit().remove(); 
     // Update existing elements 
     bars.transition() 
     .duration(300) 
     .ease("linear") 
     .call(renderBar); 
     // Add new elements (say new data has 5 bars, this would add the additional 2) 
     bars.enter().append('rect') 
     .transition() 
     .duration(300) 
     .ease("linear") 
     .call(renderBar); 
    }) 
} 

기본적으로 추가 및 업데이트 할 때 동일한 루틴을 반복하므로 renderBar 함수를 만들었습니다.

http://plnkr.co/edit/X3vZp5sReOWBsuZrxf8D?p=preview

+0

먼저,시의 적절하고 철저한 답변을 해주셔서 감사드립니다. 한 가지 질문 : updateChart()/renderBar() 함수에 다른 것을 추가하지 않고 팁이 제대로 업데이트되고 있습니다. 기대 되는가? – gpwilson

+0

우선, 감사 할 내용이 없습니다. 둘째, 네, 최신 정보가있는 막대가 이벤트를 계속 참조하면서 현재 세 개의 바 (plnkr에서) 만 업데이트하므로 팁이 올바르게 업데이트됩니다. 새 데이터에 추가 막대를 추가하면 추가 막대에 대한 이벤트를 만들어야합니다. – torresomar

관련 문제