簡體   English   中英

帶有路徑和SVG的d3動畫折線圖

[英]d3 Animated Line Chart with Path and SVG

我正在嘗試將此處的動畫折線示例調整為折線圖

 function displayGraph(id, data, width, height, interpolation, animate, updateDelay, transitionDelay) { // create an SVG element inside the #graph div that fills 100% of the div var graph = d3.select(id).append("svg:svg").attr("width", "100%").attr("height", "100%"); // create a simple data array that we'll plot with a line (this array represents only the Y values, X will just be the index location) // X scale will fit values from 0-10 within pixels 0-100 var x = d3.scale.linear().domain([0, 48]).range([-5, width]); // starting point is -5 so the first value doesn't show and slides off the edge as part of the transition // Y scale will fit values from 0-10 within pixels 0-100 var y = d3.scale.linear().domain([0, 10]).range([0, height]); // create a line object that represents the SVN line we're creating var line = d3.svg.line() // assign the X function to plot our line as we wish .x(function(d, i) { // verbose logging to show what's actually being done //console.log('Plotting X value for data point: ' + d + ' using index: ' + i + ' to be at: ' + x(i) + ' using our xScale.'); // return the X coordinate where we want to plot this datapoint return x(i); }) .y(function(d) { // verbose logging to show what's actually being done //console.log('Plotting Y value for data point: ' + d + ' to be at: ' + y(d) + " using our yScale."); // return the Y coordinate where we want to plot this datapoint return y(d); }) .interpolate(interpolation) // display the line by appending an svg:path element with the data line we created above graph.append("svg:path").attr("d", line(data)); // or it can be done like this //graph.selectAll("path").data([data]).enter().append("svg:path").attr("d", line); function redrawWithAnimation() { // update with animation graph.selectAll("path") .data([data]) // set the new data .attr("transform", "translate(" + x(1) + ")") // set the transform to the right by x(1) pixels (6 for the scale we've set) to hide the new value .attr("d", line) // apply the new data values ... but the new value is hidden at this point off the right of the canvas .transition() // start a transition to bring the new value into view .ease("linear") .duration(transitionDelay) // for this demo we want a continual slide so set this to the same as the setInterval amount below .attr("transform", "translate(" + x(0) + ")"); // animate a slide to the left back to x(0) pixels to reveal the new value /* thanks to 'barrym' for examples of transform: https://gist.github.com/1137131 */ } function redrawWithoutAnimation() { // static update without animation graph.selectAll("path") .data([data]) // set the new data .attr("d", line); // apply the new data values } setInterval(function() { if (animate) { redrawWithAnimation(); } else { redrawWithoutAnimation(); } }, updateDelay); } //displayGraph // input data var data = [3, 6, 2, 7, 5, 2, 1, 3, 8, 9, 2, 5, 9, 3, 6, 3, 6, 2, 7, 5, 2, 1, 3, 8, 9, 2, 5, 9, 2, 7, 5, 2, 1, 3, 8, 9, 2, 5, 9, 3, 6, 2, 7, 5, 2, 1, 3, 8, 9, 2, 9]; // display displayGraph("#graph1", data, 300, 30, "basis", true, 1000, 1000); // update data setInterval(function() { var v = data.shift(); // remove the first element of the array data.push(v); // add a new element to the array (we're just taking the number we just shifted off the front and appending to the end) }, 1000); 
 path { stroke: steelblue; stroke-width: 1; fill: none; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <div id="graph1" class="aGraph" style="width:300px; height:30px;"></div> 

雖然在示例中我們繪制了一條簡單的線,所以數據由x值的數組表示,即y為索引,我的數據集就像

var data=[ 
{"progress":42.3,"words":2116,"lr":0.288598,"loss":4.07032,"eta":"0h0m"}, {"progress":44,"words":2197,"lr":0.279892,"loss":4.06091,"eta":"0h0m"},{"progress":45.7,"words":2279,"lr":0.27161,"loss":4.053332,"eta":"0h0m"},{"progress":46.6,"words":2364,"lr":0.267103,"loss":4.052618,"eta":"0h0m"},{"progress":49.1,"words":2449,"lr":0.254353,"loss":4.055149,"eta":"0h0m"}, {"progress":50.9,"words":2532,"lr":0.245493,"loss":4.057263,"eta":"0h0m"},{"progress":52.7,"words":2617,"lr":0.236479,"loss":4.059458,"eta":"0h0m"},{"progress":57,"words":2833,"lr":0.215139,"loss":4.056543,"eta":"0h0m"},{"progress":58.8,"words":2920,"lr":0.205817,"loss":4.03259,"eta":"0h0m"},{"progress":61.5,"words":3046,"lr":0.192411,"loss":3.980249,"eta":"0h0m"},{"progress":64.2,"words":3175,"lr":0.178891,"loss":3.914494,"eta":"0h0m"},{"progress":66,"words":3262,"lr":0.170031,"loss":3.905593,"eta":"0h0m"},{"progress":67.8,"words":3345,"lr":0.161171,"loss":3.912257,"eta":"0h0m"},
 {"progress":69.4,"words":3425,"lr":0.152928,"loss":3.917797,"eta":"0h0m"},
{"progress":71,"words":3499,"lr":0.145031,"loss":3.922638,"eta":"0h0m"},{"progress":72.8,"words":3587,"lr":0.136055,"loss":3.927278,"eta":"0h0m"},
 {"progress":75.4,"words":3714,"lr":0.123112,"loss":3.932528,"eta":"0h0m"},{"progress":77.1,"words":3799,"lr":0.114638,"loss":3.919754,"eta":"0h0m"},{"progress":78.9,"words":3885,"lr":0.105701,"loss":3.877759,"eta":"0h0m"}
]

我想將x表示數據對象的progress值,同時將lrloss值表示為y ,但是我不知道在繪制兩個軸時如何保持動畫。

[更新]首先嘗試如下

 function displayGraph(id, data, width, height, interpolation, animate, updateDelay, transitionDelay) { var margin = { top: 30, right: 20, bottom: 30, left: 30 }, width = width - margin.left - margin.right, height = height - margin.top - margin.bottom; var graph = d3.select(id) .append("svg:svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var x = d3.scale.linear().domain([0, data.length]).range([-data.length, width]); var y = d3.scale.linear().domain([0, d3.max(data, function(d) { return d.lr })]).range([height, 0]); var y2 = d3.scale.linear().domain([0, d3.max(data, function(d) { return d.loss })]).range([height, 0]); var xAxis = d3.svg.axis().scale(x) .orient("bottom").ticks(10); var yAxis = d3.svg.axis().scale(y) .orient("left").ticks(10); var line = d3.svg.line() .x(function(d, i) { return x(i); }) .y(function(d) { return y(d.lr); }) .interpolate(interpolation) graph.append("svg:path").attr("d", line(data)).attr('stroke', function(d) { return "blue" }); graph.append("g") // Add the X Axis .attr('stroke', function(d) { return "steelblue" }) .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); graph.append("g") // Add the Y Axis .attr('stroke', function(d) { return "steelblue" }) .attr("class", "y axis") .call(yAxis); function redrawWithAnimation() { graph.selectAll("path") .data([data]) .attr("transform", "translate(" + x(1) + ")") .attr("d", line) .transition() .ease("linear") .duration(transitionDelay) .attr("transform", "translate(" + x(0) + ")"); } function redrawWithoutAnimation() { graph.selectAll("path") .data([data]) .attr("d", line); } setInterval(function() { if (animate) { redrawWithAnimation(); } else { redrawWithoutAnimation(); } }, updateDelay); } //displayGraph var data = []; var dataIn = [{ "progress": 42.3, "words": 2116, "lr": 0.288598, "loss": 4.07032, "eta": "0h0m" }, { "progress": 44, "words": 2197, "lr": 0.279892, "loss": 4.06091, "eta": "0h0m" }, { "progress": 45.7, "words": 2279, "lr": 0.27161, "loss": 4.053332, "eta": "0h0m" }, { "progress": 46.6, "words": 2364, "lr": 0.267103, "loss": 4.052618, "eta": "0h0m" }, { "progress": 49.1, "words": 2449, "lr": 0.254353, "loss": 4.055149, "eta": "0h0m" }, { "progress": 50.9, "words": 2532, "lr": 0.245493, "loss": 4.057263, "eta": "0h0m" }, { "progress": 52.7, "words": 2617, "lr": 0.236479, "loss": 4.059458, "eta": "0h0m" }, { "progress": 57, "words": 2833, "lr": 0.215139, "loss": 4.056543, "eta": "0h0m" }, { "progress": 58.8, "words": 2920, "lr": 0.205817, "loss": 4.03259, "eta": "0h0m" }, { "progress": 61.5, "words": 3046, "lr": 0.192411, "loss": 3.980249, "eta": "0h0m" }, { "progress": 64.2, "words": 3175, "lr": 0.178891, "loss": 3.914494, "eta": "0h0m" }, { "progress": 66, "words": 3262, "lr": 0.170031, "loss": 3.905593, "eta": "0h0m" }, { "progress": 67.8, "words": 3345, "lr": 0.161171, "loss": 3.912257, "eta": "0h0m" }, { "progress": 69.4, "words": 3425, "lr": 0.152928, "loss": 3.917797, "eta": "0h0m" }, { "progress": 71, "words": 3499, "lr": 0.145031, "loss": 3.922638, "eta": "0h0m" }, { "progress": 72.8, "words": 3587, "lr": 0.136055, "loss": 3.927278, "eta": "0h0m" }, { "progress": 75.4, "words": 3714, "lr": 0.123112, "loss": 3.932528, "eta": "0h0m" }, { "progress": 77.1, "words": 3799, "lr": 0.114638, "loss": 3.919754, "eta": "0h0m" }, { "progress": 78.9, "words": 3885, "lr": 0.105701, "loss": 3.877759, "eta": "0h0m" } ] // display displayGraph("#graph1", dataIn, 600, 200, "basis", true, 750, 1500); //linear // update data setInterval(function() { var v = dataIn.shift(); if (v) dataIn.push(v); }, 1000); 
 path { /*stroke: steelblue;*/ stroke-width: 1; fill: none; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <div id="graph1" class="aGraph" style="width:600px; height:200px;"></div> 

這里有幾個問題

  • 我想點對點推送新數據,即我想執行以下操作

     setInterval(function() { var v = dataIn.shift(); if(v) data.push(v); }, 1000); 

因此data將獲得一個新值以模擬來自數據源的傳入數據;

  • 因此,折線圖應轉換為一個點(就像現在一樣),但不能重復該范圍內的“舊”值。
  • 我不知道為什么y軸表示沒有標簽,而x軸是在做;

[ATTEMPT 3]在最后的測試中,我按照建議將圖形添加到組中,以便平移正常工作並顯示y軸標簽。 我還添加了有關數據更新的其他domain 這已修復了重繪圖形時的前一個問題:

x.domain([0, 100]); // max(x) is 100
    y.domain([0, d3.max(data, function(d) {
      return d.lr;
    })]);

並且我能夠在每次更新時向data數組添加一個新點:

// update data
setInterval(function() {
  var v = dataIn.shift();
  if (v) data.push(v);
}, 1000);

我有的最后一個問題是, y軸上的比例似乎仍然是錯誤的,因為我希望與y軸進度成比例,該進度應該是data.progress值,但我不知道如何。

 function displayGraph(id, data, width, height, interpolation, animate, updateDelay, transitionDelay) { var margin = { top: 30, right: 20, bottom: 30, left: 30 }, width = width - margin.left - margin.right, height = height - margin.top - margin.bottom; var svg = d3.select(id) .append("svg:svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) var graph = svg.append('g') .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var x = d3.scale.linear().domain([0, 100]).range([0, width]); // max(x) is 100 var y = d3.scale.linear().domain([0, 1]).range([height, 0]); // max(y) is 1 var line = d3.svg.line() .x(function(d, i) { return x(i); }) .y(function(d) { return y(d.lr); }) .interpolate(interpolation) var xAxis = d3.svg.axis().scale(x) .orient("bottom").ticks(10); var yAxis = d3.svg.axis().scale(y) .orient("left").ticks(10); graph.append("svg:path") .attr("d", line(data)) .attr('stroke', function(d) { return "blue" }); graph.append("g") // Add the X Axis .attr('stroke', function(d) { return "steelblue" }) .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); graph.append("g") // Add the Y Axis .attr('stroke', function(d) { return "steelblue" }) .attr("class", "y axis") .call(yAxis); function redrawWithAnimation() { //x.domain(d3.extent(data, function(d,i) { return i; })); x.domain([0, 100]); // max(x) is 100 y.domain([0, d3.max(data, function(d) { return d.lr; })]); graph.selectAll("path") .data([data]) .attr("transform", "translate(" + x(1) + ")") .attr("d", line) .transition() .ease("linear") .duration(transitionDelay) .attr("transform", "translate(" + x(0) + ")"); } function redrawWithoutAnimation() { // static update without animation graph.selectAll("path") .data([data]) // set the new data .attr("d", line); // apply the new data values } setInterval(function() { if (animate) { redrawWithAnimation(); } else { redrawWithoutAnimation(); } }, updateDelay); } //displayGraph var data = []; var dataIn = [{ "progress": 42.3, "words": 2116, "lr": 0.288598, "loss": 4.07032, "eta": "0h0m" }, { "progress": 44, "words": 2197, "lr": 0.279892, "loss": 4.06091, "eta": "0h0m" }, { "progress": 45.7, "words": 2279, "lr": 0.27161, "loss": 4.053332, "eta": "0h0m" }, { "progress": 46.6, "words": 2364, "lr": 0.267103, "loss": 4.052618, "eta": "0h0m" }, { "progress": 49.1, "words": 2449, "lr": 0.254353, "loss": 4.055149, "eta": "0h0m" }, { "progress": 50.9, "words": 2532, "lr": 0.245493, "loss": 4.057263, "eta": "0h0m" }, { "progress": 52.7, "words": 2617, "lr": 0.236479, "loss": 4.059458, "eta": "0h0m" }, { "progress": 57, "words": 2833, "lr": 0.215139, "loss": 4.056543, "eta": "0h0m" }, { "progress": 58.8, "words": 2920, "lr": 0.205817, "loss": 4.03259, "eta": "0h0m" }, { "progress": 61.5, "words": 3046, "lr": 0.192411, "loss": 3.980249, "eta": "0h0m" }, { "progress": 64.2, "words": 3175, "lr": 0.178891, "loss": 3.914494, "eta": "0h0m" }, { "progress": 66, "words": 3262, "lr": 0.170031, "loss": 3.905593, "eta": "0h0m" }, { "progress": 67.8, "words": 3345, "lr": 0.161171, "loss": 3.912257, "eta": "0h0m" }, { "progress": 69.4, "words": 3425, "lr": 0.152928, "loss": 3.917797, "eta": "0h0m" }, { "progress": 71, "words": 3499, "lr": 0.145031, "loss": 3.922638, "eta": "0h0m" }, { "progress": 72.8, "words": 3587, "lr": 0.136055, "loss": 3.927278, "eta": "0h0m" }, { "progress": 75.4, "words": 3714, "lr": 0.123112, "loss": 3.932528, "eta": "0h0m" }, { "progress": 77.1, "words": 3799, "lr": 0.114638, "loss": 3.919754, "eta": "0h0m" }, { "progress": 78.9, "words": 3885, "lr": 0.105701, "loss": 3.877759, "eta": "0h0m" } ] // display displayGraph("#graph1", data, 600, 200, "basis", true, 1000, 1000); //linear // update data setInterval(function() { var v = dataIn.shift(); if (v) data.push(v); }, 1000); 
 path { /*stroke: steelblue;*/ stroke-width: 1; fill: none; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <div id="graph1" class="aGraph" style="width:600px; height:200px;"></div> 

另一個問題是,在給出此代碼的情況下, x的范圍不會隨新值擴展,因此我從圖中獲得了y值:

在此處輸入圖片說明

y軸不顯示的原因是因為它在svg之外。 如果您將一個組添加到svg並通過邊際翻譯將其可見。

var svg = d3.select(id)
  .append("svg:svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
var graph = svg.append('g')
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

您能否說明一下目前添加數據的方式出了什么問題? 在我看來很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM