2017-02-25 60 views
1

我正在嘗試創建一個具有'參加者'和'硬幣'的條形圖。數據正在從外部文件讀取,我想在數據更改時更新圖表(或每隔幾秒鐘檢查一次文件並更新數據)。我一直試圖沿着mbostock's關於總體更新模式的教程進行學習,但已經有一段時間甚至開始適應我自己的圖表。我沒有發現處理從外部文件轉換數據的其他問題/答案,但是如果我錯過了某些內容,請告訴我。所以,就這樣,我把你全部變成了!D3 - 從外部文件讀取更新數據後的轉換

這是我目前的JS代碼:

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() { 

} 

我還要提到的是這是第一次真正嘗試與D3進行深入分析。我希望我不會錯過太明顯的東西!提前感謝您的任何幫助,建議或推動正確的方向!

**編輯注意條形圖是試圖添加功能的樣本發現here

編輯2:這裏添加.tsv格式爲更好的格式:

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

哎,你分享的是一點點的TSV所以我們可以試一下嗎? – 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功能,因爲我們基本上在添加和更新重複相同的程序。

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部分:

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

+0

首先,非常感謝您的及時和徹底的迴應。一個問題:我的技巧正在更新,而無需向updateChart()/ renderBar()函數添加任何其他內容。這是預期的嗎? – gpwilson

+0

首先,你沒有什麼值得感謝的。其次,是的,提示會正確更新,因爲我們只更新當前的三個小節(在plnkr中),小節仍然引用了這些事件,因此具有最新的信息。嘗試在新數據中添加額外的欄,您將看到您需要爲該附加欄創建事件。 – torresomar