2016-12-07 168 views
2

基於此tutorial我創建了兩個圖,每個圖都有兩個度量。每隔5秒鐘從csv文件中讀取第一個圖形中顯示的cpu%user和cpu%system以及第二個圖形中使用的內存空閒內存。在d3.js中自動更新圖表

問題是,只更新第一個圖的第一行。 當我刪除cpu%用戶時,它只更新cpu%系統。我無法使用它們的座標軸更新這兩個圖形中的所有度量標準。

這裏有什麼明顯的錯誤嗎? 是否有任何其他教程與我在d3.js中嘗試做的類似?

我的代碼

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> /* set the CSS */ 

body { font: 12px Arial;} 

path { 
    stroke: black; 
    stroke-width: 2; 
    fill: none; 
} 

.axis path, 
.axis line { 
    fill: none; 
    stroke: grey; 
    stroke-width: 1; 
    shape-rendering: crispEdges; 
} 


</style> 
<body> 

<!-- load the d3.js library -->  
<script src="http://d3js.org/d3.v3.min.js"></script> 

<script> 

// Set the dimensions of the canvas/graph 
var margin = {top: 30, right: 20, bottom: 30, left: 50}, 
    width = 350 - margin.left - margin.right, 
    height = 250 - margin.top - margin.bottom; 

// Parse the date/time 
var parseTime = d3.time.format("%d-%m-%Y:%H:%M").parse; 

// Set the ranges 
var x = d3.time.scale().range([0, width]); 
var y = d3.scale.linear().range([height, 0]); 

// Define the axes 
var xAxis = d3.svg.axis().scale(x) 
    .orient("bottom").ticks(5); 

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

// Define the line 
var user = d3.svg.line() 
    .x(function(d) { return x(d.timestamp); }) 
    .y(function(d) { return y(d.user); }); 

var system = d3.svg.line() 
    .x(function(d) { return x(d.timestamp); }) 
    .y(function(d) { return y(d.system); }); 

var memFree = d3.svg.line() 
    .x(function(d) { return x(d.timestamp); }) 
    .y(function(d) { return y(d.memFree); }); 

var memUsed = d3.svg.line() 
    .x(function(d) { return x(d.timestamp); }) 
    .y(function(d) { return y(d.memUsed); }); 

// Adds the svg canvas 
var chart1 = 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 + ")"); 
var chart2 = 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 + ")"); 

// Get the data 
d3.csv("data.csv", function(error, data) { 
    data.forEach(function(d) { 
      d.timestamp = parseTime(d.timestamp); 
      d.user = +d.user; 
      d.system = +d.system; 
      d.memFree = +d.memFree; 
      d.memUsed = +d.memUsed; 
    }); 

    var min = d3.min(data, function(d) { return Math.min(d.user, d.system); }); 
    x.domain(d3.extent(data, function(d) { return d.timestamp; })); 
    y.domain([min, d3.max(data, function(d) { return Math.max(d.user, d.system); })]); 

     chart1.append("path") 
     .data([data]) 
     .attr("class", "userLine") 
     .style("stroke", "green") 
     .attr("d", user(data)); 

    chart1.append("path") 
     .data([data]) 
     .attr("class", "systemLine") 
     .style("stroke", "blue") 
     .attr("d", system(data)); 

    // Add the X Axis 
    chart1.append("g") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis); 

    // Add the Y Axis 
    chart1.append("g") 
     .call(yAxis); 

    chart1.append("text") 
    .attr("transform", "translate(" + (width/4) + "," + y(data[0].user) + ")") 
    .attr("text-anchor", "start") 
    .style("fill", "green") 
    .text("%user"); 

    chart1.append("text") 
    .attr("transform", "translate(" + (width/5) + "," + y(data[0].system) + ")") 
    .attr("text-anchor", "start") 
    .style("fill", "blue") 
    .text("%system"); 

}); 

d3.csv("data.csv", function(error, data) { 
    data.forEach(function(d) { 
      d.timestamp = parseTime(d.timestamp); 
      d.user = +d.user; 
      d.system = +d.system; 
      d.memFree = +d.memFree; 
      d.memUsed = +d.memUsed; 
    }); 

    // Scale the range of the data 
    var min = d3.min(data, function(d) { return Math.min(d.memFree, d.memUsed); }); 
    x.domain(d3.extent(data, function(d) { return d.timestamp; })); 
    y.domain([min, d3.max(data, function(d) { return Math.max(d.memFree, d.memUsed); })]); 

    chart2.append("path") 
     .data([data]) 
     .attr("class", "memFreeLine") 
     .style("stroke", "green") 
     .attr("d", memFree(data)); 

    chart2.append("path") 
     .data([data]) 
     .attr("class", "memUsedLine") 
     .style("stroke", "blue") 
     .attr("d", memUsed(data)); 

    // Add the X Axis 
    chart2.append("g") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis); 

    // Add the Y Axis 
    chart2.append("g") 
     .call(yAxis); 

    chart2.append("text") 
    .attr("transform", "translate(" + (width/4) + "," + y(data[0].memFree) + ")") 
    .attr("text-anchor", "start") 
    .style("fill", "green") 
    .text("memFree"); 

    chart2.append("text") 
    .attr("transform", "translate(" + (width/2) + "," + y(data[0].memUsed) + ")") 
    .attr("text-anchor", "start") 
    .style("fill", "blue") 
    .text("memUsed"); 

}); 

setInterval(function() { 
    updateChart1(); 
    updateChart2(); 
}, 5000); 

// ** Update data section (Called from the onclick) 
function updateChart1() { 
    // Get the data again 
    d3.csv("data.csv", function(error, data) { 
     data.forEach(function(d) { 
      d.timestamp = parseTime(d.timestamp); 
      d.user = +d.user; 
      d.system = +d.system; 
      d.memFree = +d.memFree; 
      d.memUsed = +d.memUsed; 
     }); 

    var min = d3.min(data, function(d) { return Math.min(d.user, d.system); }); 
    x.domain(d3.extent(data, function(d) { return d.timestamp; })); 
    y.domain([min, d3.max(data, function(d) { return Math.max(d.user, d.system); })]); 

    // Select the section we want to apply our changes to 
    var chart1 = d3.select("svg").transition(); 

    // Make the changes 
     chart1.select(".userLine") // change the line 
      .duration(750) 
      .attr("d", user(data)); 
     chart1.select(".systemLine") // change the line 
      .duration(750) 
      .attr("d", system(data)); 

     chart1.select(".x.axis") // change the x axis 
      .duration(750) 
      .call(xAxis); 
     chart1.select(".y.axis") // change the y axis 
      .duration(750) 
      .call(yAxis); 

    }); 
} 

function updateChart2() { 

    // Get the data again 
    d3.csv("data.csv", function(error, data) { 
     data.forEach(function(d) { 
      d.timestamp = parseTime(d.timestamp); 
      d.user = +d.user; 
      d.system = +d.system; 
      d.memFree = +d.memFree; 
      d.memUsed = +d.memUsed; 
     }); 

     // Scale the range of the data again 
    var min = d3.min(data, function(d) { return Math.min(d.memFree, d.memUsed); }); 
    x.domain(d3.extent(data, function(d) { return d.timestamp; })); 
    y.domain([min, d3.max(data, function(d) { return Math.max(d.memFree, d.memUsed); })]); 

    // Select the section we want to apply our changes to 
    var chart2 = d3.select("svg").transition(); 

    // Make the changes 
     chart2.select(".memFreeLine") // change the line 
      .duration(750) 
      .attr("d", memFree(data)); 
     chart2.select(".memUsedLine") // change the line 
      .duration(750) 
      .attr("d", memUsed(data)); 
     chart2.select(".x.axis") // change the x axis 
      .duration(750) 
      .call(xAxis); 
     chart2.select(".y.axis") // change the y axis 
      .duration(750) 
      .call(yAxis); 

    }); 
} 

</script> 
</body> 
+0

我幾乎可以肯定有什麼問題,但在我寫答案之前,你可以粘貼**你的**代碼嗎? –

+0

更新了我的問題@GerardoFurtado – jimakos17

回答

1

這裏的問題是:你是選擇這兩個你updateChart函數中相同的元素:

chart1.select(".line")//class here is "line" 
     .duration(750) 
     .attr("d", user(data)); 
chart1.select(".line")//class here is "line" again! 
     .duration(750) 
     .attr("d", system(data)); 

看到了嗎?您正在爲用戶和系統數據選擇相同的類(.line)。

解決方案:

在最初的畫,設定不同的類:

chart1.append("path") 
    .data([data]) 
    .attr("class", "userLine")//specific class 
    .style("stroke", "green") 
    .attr("d", user(data)); 

chart1.append("path") 
    .data([data]) 
    .attr("class", "systemLine")//specific class 
    .style("stroke", "blue") 
    .attr("d", system(data)); 

,然後更新每個單獨的一個:

chart1.select(".userLine")//selecting different classes... 
     .duration(750) 
     .attr("d", user(data)); 
chart1.select(".systemLine")//selecting different classes... 
     .duration(750) 
     .attr("d", system(data)); 
+0

我已將行更改爲userLine,systemLine,memFreeLine和memUsedLine,現在它不更新任何內容。甚至不是第一張圖的第一行。 – jimakos17

+0

我能看到的另一個錯誤是這條線,你應該刪除:'var chart1 = d3.select(「svg」)。transition();'你遇到的問題很清楚。在這一點上,除非你創建一個工作的重要人物或者擺弄數據,否則我再也忍不住了。 –

+0

我用新的類更新了我的代碼。當我刪除行var chart1 = d3.select(「svg」)。transition();我得到一個錯誤Uncaught TypeError:chart1.select(...)。duration不是函數。謝謝你的幫助Gerardo – jimakos17