2016-04-07 4 views
0

Ich fragte mich, ob es eine Möglichkeit gibt, die Aktualisierungsgeschwindigkeit der Scatter-Plots zu ändern? Wie Sie in diesem link sehen können, wird die Streudiagramme aktualisiert, aber die Zeitlücke zwischen dem Erscheinen und Verschwinden ist unangemessen, es sieht aus wie sie blinkende Punkte sind .... Ich habe versucht, die circle.remove() -Funktion direkt über dem Kreis zu bewegen . Übergang, aber es macht keinen Unterschied.D3JS Streudiagramme aktualisieren Geschwindigkeit

Unten ist der relevante Code der Refresh-Funktion. Vielen Dank!

function updateData() { 

    // Get the data again 
    data = d3.json("2301data.php", function(error, data) { 
    data.forEach(function(d) { 
     d.dtg = parseDate(d.dtg); 
     d.temperature = +d.temperature; 
     // d.hum = +d.hum; // Addon 9 part 3 
    }); 

    // Scale the range of the data again 
    x.domain(d3.extent(data, function(d) { return d.dtg; })); 
    y.domain([0, 60]);    

    var svg = d3.select("#chart1").select("svg").select("g"); 

       svg.select(".x.axis") // change the x axis 
      .transition() 
      .duration(750) 
      .call(xAxis); 
     svg.select(".y.axis") // change the y axis 
      .transition() 
      .duration(750) 
      .call(yAxis); 
     svg.select(".line") // change the line 
      .transition() 
      .duration(750) 
      .attr("d", valueline(data)); 

    var circle = svg.selectAll("circle").data(data); 

    circle.remove() //remove old dots 

    // enter new circles 
     circle.enter() 
      .append("circle") 
      .filter(function(d) { return d.temperature > 35 }) 
      .style("fill", "red") 
      .attr("r", 3.5) 
      .attr("cx", function(d) { return x(d.dtg); }) 
      .attr("cy", function(d) { return y(d.temperature); }) 

     // Tooltip stuff after this 
     .on("mouseover", function(d) {  
      div.transition() 
       .duration(500) 
       .style("opacity", 0); 
      div.transition() 
       .duration(200) 
       .style("opacity", .9); 
      div .html(
       d.temperature + "C" + "<br>" + 
       formatTime(d.dtg)) 
       .style("left", (d3.event.pageX + 8) + "px")   
       .style("top", (d3.event.pageY - 18) + "px");}) 
     .on("mouseout", function(d) {  
      div.transition()   
       .duration(500)  
       .style("opacity", 0); 
      }); 

    circle.transition().attr("cx", function(d) { return x(d.dtg); }); 
     // exit 
     circle.exit(); 



    }); 
} 

Antwort

1

bei Ihrem Beispiel sucht, wie es läuft, erscheinen Sie jede Menge mehr Kreise in dem dom zu haben, als sichtbar sind. Dies liegt daran, dass Sie Kreise für alle Daten hinzufügen, aber nur Positionen für diejenigen angeben, die die von Ihnen festgelegten Filterkriterien erfüllen.

Es gab eine verwandte Frage neulich über Datenfilterung gegen d3 Filterung - Filtering data to conditionally render elements. Verwenden Sie die Datenfilterung, wenn Sie nichts hinzufügen möchten, verwenden Sie d3.filter, wenn Sie einige Elemente für eine spezielle Behandlung isolieren möchten (Übergänge, anderes Styling usw.).

Im Moment filtern Sie die d3-Auswahl, sobald alle Kreise hinzugefügt wurden, aber in Ihrem Fall würde ich vorschlagen, die Daten zu filtern, bevor sie zu dieser Stufe am besten sind (und wie von anderen in dieser anderen Frage vorgeschlagen)). Dies kann es schneller laufen (aber Sie sind auch von der Gnade des db-Updates durch den Blick von Ihrem Beispiel?)

data = data.filter (function(d) { return d.temperature > 35; }); // do filtering here 
var circle = svg.selectAll("circle").data(data); 

circle.exit().remove() //remove old dots 

// enter new circles 
    circle.enter() 
     .append("circle") 
     .style("fill", "red") 
     .attr("r", 3.5) 
     .attr("cx", function(d) { return x(d.dtg); }) 
     .attr("cy", function(d) { return y(d.temperature); }) 
     ... 

PS. Es ist ein bisschen verwirrend, was Sie mit dem circle.remove() und circle.exit() tun wollen. circle.remove() entfernt alle vorhandenen Kreise (auch solche, die existieren und neue Daten haben), circle.exit() am Ende wird dann keine Wirkung haben. Ich hätte nur circle.exit(). Remove(), um die zwei Aufrufe zu ersetzen, die Sie machen.

Auch ohne eine Tastenfunktion - https://bost.ocks.org/mike/constancy/ - auf Ihrem .data() - Aufruf, können Sie Punkte ein wenig bewegen. Wenn Ihre Datenpunkte IDs haben, verwenden Sie sie.

var circle = svg.selectAll("circle").data(data, function(d) { return d.id; /* or d.dtg+" "+d.temperature; if no id property */}); 
+0

Vielen Dank für Ihre schnelle Antwort. Filtern der Daten im Voraus ist eine großartige Idee. Ich habe versucht, den Code zu ändern, wie es unter [http://cpcvip.com/test1/index2.html] zu sehen ist, aber nach der Aktualisierung erscheinen die Kreise überhaupt nicht mehr. Ich habe den Code auf Fiddle [http://jsfiddle.net/badatz/voh3yke] gepostet, aber wegen des aktiven Inhalts funktioniert es nicht wirklich ... Irgendwelche Ideen? – badatz

+0

1. Sind Sie sicher, dass Sie tatsächlich eine .id-Eigenschaft haben, die für .data() aktiviert wird? Betrachtet man die Datenbankabfragen, die unter dem Diagramm erscheinen, scheint es, dass Sie nicht haben. In diesem Fall greifen Sie auf die Verkettung von .dtg und .temperatur als Schlüssel zurück. – mgraham

+0

2. Im Allgemeinen würde ich versuchen, Ihren ursprünglichen Datenanruf und Ihren Updateanruf so weit wie möglich zusammenzuführen. Abgesehen davon, dass sie die Graphenachsen erstellen, machen sie dasselbe - Daten holen und grafisch darstellen - es ist genau das, was d3 gut macht, neue Daten hinzufügen, vorhandene Daten aktualisieren, fehlende Daten entfernen. Aber lassen Sie das für, wenn Sie es so arbeiten, wie es derzeit ist. – mgraham

0

Dank mgraham wurde das Problem gelöst.! Unten ist der überarbeitete Code, falls jemand anders es braucht.

function updateData() { 

    // Get the data again 
    data = d3.json("data.php", function(error, data) { 
    data.forEach(function(d) { 
     d.dtg = parseDate(d.dtg); 
     d.temperature = +d.temperature; 
     }); 

     // Scale the range of the data again 
    x.domain(d3.extent(data, function(d) { return d.dtg; })); 
    y.domain([0, 60]); // Addon 9 part 4 

    var svg = d3.select("#chart1").select("svg").select("g"); 

    svg.select(".x.axis") // change the x axis 
      .transition() 
      .duration(750) 
      .call(xAxis); 
     svg.select(".y.axis") // change the y axis 
      .transition() 
      .duration(750) 
      .call(yAxis); 
     svg.select(".line") // change the line 
      .transition() 
      .duration(750) 
      .attr("d", valueline(data)); 


    data = data.filter (function(d) { return d.temperature > 35; }); 

    var circle = svg.selectAll("circle").data(data, function(d) { return d.dtg+" "+d.temperature;}); 
    circle.exit().remove() //remove old dots 

    // enter new circles 
     circle.enter() 
      .append("circle") 
     .style("fill", "red") 
     .attr("r", 3.5)  
      .attr("cx", function(d) { return x(d.dtg); }) 
     .attr("cy", function(d) { return y(d.temperature); }) 

    // Tooltip stuff after this 
     .on("mouseover", function(d) {  
      div.transition() 
       .duration(500) 
       .style("opacity", 0); 
      div.transition() 
       .duration(200) 
       .style("opacity", .9); 
      div .html(
       d.temperature + "C" + "<br>" + 
       formatTime(d.dtg)) 
       .style("left", (d3.event.pageX + 8) + "px")   
       .style("top", (d3.event.pageY - 18) + "px");}) 
     .on("mouseout", function(d) {  
      div.transition()   
       .duration(500)  
       .style("opacity", 0); 
      }); 

    circle.transition().attr("cx", function(d) { return x(d.dtg); }); 


    }); 
}   

</script>