2016-12-26 62 views
0

不斷翻譯整個陣列中的D3

var bardata = []; //array that holds the current value for the candlestick chart 
 
\t \t var pastRectangles = [50,12,14,15,35,64] //holds the data for the historical rectangles to be drawn 
 
\t \t var data; 
 
\t \t 
 
\t \t setInterval(function() { 
 
\t \t \t var x = Math.floor(Math.random() * 100) //generate a random whole number between 0-99 
 
\t \t \t bardata.push(x); // push that value into the bardata array 
 
\t \t // \t console.log(bardata) 
 
\t \t \t data = x; //set the value of x to data, will be used to update the pastRectangles array every 10 seconds 
 
\t \t }, 1000); 
 
\t \t 
 
\t \t var height = 900 
 
\t \t \t , width = 900 
 
\t \t \t , barWidth = 50 
 
\t \t \t , barOffset = 55; 
 

 
\t \t var offset = pastRectangles.length * (barOffset + barWidth); 
 

 

 
\t \t var scale = d3.scale.linear() 
 
\t \t \t .range([0, pastRectangles]) 
 
\t \t \t .domain([0, height]); 
 
\t \t var svg = d3.select('body') 
 
\t \t \t .append('svg') 
 
\t 
 
     .attr('width', width) 
 
\t \t \t .attr('height', height) 
 
\t \t \t .style('background', 'black') 
 
\t \t \t .append("g") 
 
\t \t \t .attr("class", "rectangles") 
 
\t \t \t 
 
\t \t 
 
\t \t update(pastRectangles[pastRectangles.length-1]); 
 
\t \t pastDraw(); // call post draw to draw the dummy data first before the update function starts running 
 
\t 
 
\t \t 
 
\t \t \t function pastDraw() 
 
\t \t { 
 
\t \t \t var pastRect = svg.selectAll('rect').data(pastRectangles); \t \t \t \t \t //This function will loop through the pastRectangles array and will 
 
\t \t  pastRect.enter() \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t //draw a rectange for every index in the array 
 
\t \t \t \t .append("rect") \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t //The reason for not using bardata is that it only holds one value 
 
\t \t \t \t .attr("g", "rectangles") 
 
\t \t \t \t .attr("x", function(d,i){return i * (barWidth+barOffset)}) \t \t \t \t //every second and therefore a second array is needed to hold the 
 
\t \t \t \t .attr("y", function(d){return height - d}) \t \t \t \t \t \t \t \t //historical data 
 
\t \t \t \t .attr("height", function(d){return d}) \t \t \t \t \t \t \t \t \t 
 
\t \t \t \t .attr("width", 60) 
 
\t \t \t \t .attr("id", "history") 
 
\t \t \t \t .attr("fill", "steelblue") 
 
\t \t \t \t pastRect.transition() 
 
\t \t \t \t .duration(1000) 
 
\t \t \t \t .ease('linear') 
 
\t \t \t \t .attr("height", function (d) { 
 
\t \t \t \t \t return d 
 
\t \t \t \t }) 
 
\t \t \t \t pastRect.exit() 
 
\t \t } 
 
\t \t function update(bardata) { 
 
\t \t \t \t var rect = svg.selectAll('rect').data([bardata]); \t \t \t \t \t \t \t //This function essentially draws a new rectangle for every 
 
\t \t \t \t rect.enter() \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t //value of bardata, however, because bardata is constantly 
 
\t \t \t \t .append("rect") \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t //removing the current value for a new value every second 
 
\t \t \t \t .attr("x",offset) \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t //it gives the illusion of one rectangle updating regularly 
 
\t \t \t \t .attr("y", function(d){return height - d}) 
 
\t \t \t \t .attr("id", "updateBar") 
 
\t \t \t \t .attr("height", bardata) \t \t \t \t \t \t \t \t \t \t 
 
\t \t \t \t .attr("width", 60) 
 
\t \t \t \t .attr("fill", "steelblue") 
 
\t \t \t \t rect.transition() 
 
\t \t \t \t .duration(1000) 
 
\t \t \t \t .ease('linear') 
 
\t \t \t \t .attr("height", function (d) { 
 
\t \t \t \t \t return d 
 
\t \t \t \t }) 
 
\t \t \t 
 
\t \t \t 
 
// \t \t \t \t rect.exit().transition() 
 
//  \t \t \t .duration(1000) 
 
//  \t \t \t .attr("transform", "translate(-80,0)") 
 
// \t \t \t \t .remove(); 
 
// \t \t 
 
\t \t \t 
 
\t \t \t //console.log(bardata); 
 
\t \t } 
 
\t \t function moveBar() 
 
\t \t { 
 
\t \t \t svg.selectAll("#history") 
 
\t \t \t .transition() 
 
     \t \t .duration(1000) 
 
     \t \t .attr("transform", "translate(-80,0)") 
 
\t \t \t svg.select("#updateRect") 
 
\t \t \t .transition() 
 
     \t \t .duration(1000) 
 
     \t \t .attr("transform", "translate(80,0)") 
 
\t \t } 
 
\t 
 
\t \t setInterval(function() { 
 
\t \t \t update(bardata); //call the update function with the current value of bardata 
 
\t \t \t bardata.shift(); // remove the the last index of the array from bardata 
 
\t \t }, 1000) 
 
\t \t \t setInterval(function() { 
 
\t \t \t pastRectangles.push(data) //update pastrectangles array with the most current value of x every 10 seconds 
 
\t \t \t pastDraw(); // call the pastDraw function to draw the latest recatngle 
 
\t \t \t moveBar(); 
 

 
\t \t }, 10000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

與D3瞎搞,並試圖讓現場柱狀圖,我希望它表現得就像人K線 參考圖像誰不知道那是什麼:http://www.chart-formations.com/stock-charts/_img/candlestickChart.gif

我想要一個實時更新欄,經過一段時間後我想在它的左邊畫一個矩形,並且我已經成功地使用了兩個數組,每秒都有一個值用於繪製更新欄,另一個值用於繪製更新欄不適合所有過去的矩形數據。

然而,pastRectangles中的矩形是以錯誤的順序繪製的,我只能假設這是因爲當d3通過數據集時,它會從數組的開始到數組的末尾,我嘗試了倒轉該陣列嘗試防止,但仍然沒有幫助。

我已經修復它,並得到它的工作有點我是如何,但我無法翻譯它,我想如何,它似乎只是將最新的矩形轉換爲數組,而不是整個數組,每次都有,無論如何要做到這一點?或者,也可以每次都向前移動更新欄。

回答

0

相反的整個數字陣列轉移到左側,我終於寫一個simpe moveBars功能

function moveBar() 
     { 
      var bar = svg.selectAll("#updateBar")   
       .transition() 
       .duration(50) 
       .attr("transform", "translate("+move+",0)") 
       move += (barWidth+barOffset); 
       console.log(move) 
     } 

移動到右邊的updatebar然後,我剛打電話,在我的pastDraw()功能得到每十秒鐘

\t var bardata = []; //array that holds the current value for the candlestick chart 
 
\t \t var pastRectangles = [50,12,14,15,35,64] //holds the data for the historical rectangles to be drawn 
 
\t \t var data 
 
\t \t \t , height = 250 
 
\t \t \t , width = 800 
 
\t \t \t , barWidth = 50 
 
\t \t \t , barOffset= 55; 
 
\t \t var move = 0; 
 
\t \t 
 
\t \t 
 
\t \t setInterval(function() { 
 
\t \t \t var x = Math.floor(Math.random() * 100) //generate a random whole number between 0-99 
 
\t \t \t bardata.push(x); // push that value into the bardata array 
 
\t \t \t data = x; //set the value of x to data, will be used to update the pastRectangles array every 10 seconds 
 
\t \t }, 1000); 
 
\t \t 
 
\t \t data = (barOffset+barOffset) 
 
\t \t var offset = pastRectangles.length * (barOffset + barWidth); 
 

 
\t \t 
 
\t \t var scale = d3.scale.linear() 
 
\t \t \t .range([0, pastRectangles]) 
 
\t \t \t .domain([0, height]); 
 
\t \t var svg = d3.select('body') 
 
\t \t \t .append('svg') 
 
\t \t \t .attr('width', width) 
 
\t \t \t .attr('height', height) 
 
\t \t \t .style('background', 'red') 
 
\t \t \t .append("g") 
 
\t \t \t .attr("class", "rectangles") 
 
\t \t \t 
 
\t \t 
 
\t \t \t update(pastRectangles[pastRectangles.length-1]); 
 
\t \t \t pastDraw() 
 
\t \t \t 
 
\t \t 
 
\t \t \t function pastDraw() 
 
\t \t \t { 
 
\t \t \t \t var pastRect = svg.selectAll('rect').data(pastRectangles); \t \t \t \t \t //This function will loop through the pastRectangles array and will 
 
\t \t \t \t pastRect.enter() \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t //draw a rectange for every index in the array 
 
\t \t \t \t \t .append("rect") \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t //The reason for not using bardata is that it only holds one value 
 
\t \t \t \t \t .attr("g", "rectangles") 
 
\t \t \t \t \t .attr("x", function(d,i){return i * (barWidth+barOffset)}) \t \t \t \t //every second and therefore a second array is needed to hold the 
 
\t \t \t \t \t .attr("y", function(d){return height - d}) \t \t \t \t \t \t \t \t //historical data 
 
\t \t \t \t \t .attr("height", function(d){return d}) \t \t \t \t \t \t \t \t \t 
 
\t \t \t \t \t .attr("width", 60) 
 
\t \t \t \t \t .attr("id", "history") 
 
\t \t \t \t \t .attr("fill", "steelblue") 
 
\t \t \t \t \t pastRect.transition() 
 
\t \t \t \t \t .duration(1000) 
 
\t \t \t \t \t .ease('linear') 
 
\t \t \t \t \t .attr("height", function (d) { 
 
\t \t \t \t \t \t return d 
 
\t \t \t \t \t }) 
 
\t \t \t \t \t pastRect.exit() 
 
\t \t \t \t \t var bar = svg.selectAll("#updateBar") \t \t \t 
 
\t \t \t \t \t .transition() 
 
\t \t \t \t \t .duration(1000) 
 
\t \t \t \t \t .attr("transform", "translate("+move+",0)") 
 
\t \t \t \t \t move += (barWidth+barOffset); 
 

 
\t \t \t \t \t 
 
\t \t \t \t setTimeout(function() 
 
\t \t \t { 
 
\t \t \t \t \t pastRectangles.push(data) 
 
\t \t \t \t \t 
 
\t \t \t \t \t pastDraw(); 
 
\t \t \t },30000) 
 

 

 
\t \t \t } 
 
\t \t function update(bardata) { 
 
\t \t \t \t var rect = svg.selectAll('rect').data([bardata]); \t \t \t \t \t \t \t //This function essentially draws a new rectangle for every 
 
\t \t \t \t rect.enter() \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t //value of bardata, however, because bardata is constantly 
 
\t \t \t \t .append("rect") \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t //removing the current value for a new value every second 
 
\t \t \t \t .attr("x",offset) \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t //it gives the illusion of one rectangle updating regularly 
 
\t \t \t \t .attr("y", function(d){return height - d}) 
 
\t \t \t \t .attr("id", "updateBar") 
 
\t \t \t \t .attr("height", bardata) \t \t \t \t \t \t \t \t \t \t 
 
\t \t \t \t .attr("width", 60) 
 
\t \t \t \t .attr("fill", "white") 
 
\t \t \t \t .attr("stroke", "black") 
 
\t \t \t \t rect.transition() 
 
\t \t \t \t .duration(1000) 
 
\t \t \t \t .ease('linear') 
 
\t \t \t \t .attr("height", function (d) { 
 
\t \t \t \t \t return d 
 
\t \t \t \t }) 
 
\t \t \t 
 
\t \t \t 
 
\t \t \t \t rect.exit(); 
 
\t \t \t 
 

 

 
\t \t 
 
\t \t \t 
 
\t \t \t //console.log(bardata); 
 
\t \t } 
 
\t \t 
 
\t \t setInterval(function() { 
 
\t \t \t update(bardata); //call the update function with the current value of bardata 
 
\t \t \t bardata.shift(); // remove the the last index of the array from bardata 
 
\t \t \t 
 
\t \t }, 1000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

運行在Chrome這個代碼可以忒稱爲因Chrome瀏覽器如何處理SetInterval()而宕機,因此我選擇使用遞歸的setTimeouts()而不是