web-dev-qa-db-fra.com

Mettre à jour dynamiquement les données du graphique dans D3

Je travaille sur une visualisation en temps réel des données entrantes. J'utilise D3 pour la visualisation et j'ai commencé sur la base de cet exemple: http://bl.ocks.org/mbostock/3883195

Voici la version sur laquelle je travaille actuellement:

  var margin = {top: 20, right: 20, bottom: 30, left: 50},
  width = 500 - margin.left - margin.right,
  height = 300 - margin.top - margin.bottom;

  var x = d3.time.scale().range([0, width]);
  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");

  var area = d3.svg.area()
      .x(function(d) { return x(d.x); })
      .y0(height)
      .y1(function(d) { return y(d.y); });

  var svg = d3.select("div#chart").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 data = [[1,1],[2,3],[3,2],[4,4]];

  var dataCallback = function(d) {
    d.x = +d[0];
    d.y = +d[1];
  };
  data.forEach(dataCallback);

  x.domain(d3.extent(data, function(d) { return d.x; }));
  y.domain([0, d3.max(data, function(d) { return d.y; })]);

  svg.append("path")
      .datum(data)
      .attr("class", "area")
      .attr("d", area);

  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", ".71em")
      .style("text-anchor", "end")
      .text("Number of Messages");

Cela produit le graphique suivant:

simple graph

Maintenant, comme il devrait se mettre à jour régulièrement, je voulais mettre à jour dynamiquement les données du graphique en utilisant le code suivant:

  var n = svg.selectAll("path").data([5,20])
  n.enter();
  n.exit().remove();

Mais cela ne fonctionne pas. Je suis nouveau sur D3 et j'apprends toujours les bases. Idéalement, la visualisation du graphique se déplace vers la gauche et les nouvelles données sont affichées dans le graphique. Mais jusqu'à présent, je ne peux même pas y ajouter de nouvelles données. Quelqu'un pourrait-il m'aider avec ça? J'ai également recherché des exemples similaires à celui-ci, mais je n'ai rien trouvé qui m'a vraiment aidé jusqu'à présent.

25
str

d3 est assez bon pour garder une trace des données qui ont été ajoutées et de ce qui est supprimé - il le fait avec les jointures. Jetez un oeil à http://bl.ocks.org/mbostock/3808218

SI nous utilisons la liaison de données (au lieu de "datum")

svg.append("path")
  .data([data])
  .attr("class", "area")
  .attr("d", area);

puis à la mise à jour, faites quelque chose comme:

// update the list of coordinates
data.splice(0,1);
data.Push([5,20]);

// re-decorate the last, newly added item
dataCallback(data[data.length - 1]);

// You will also need to update your axes
x.domain(d3.extent(data, function(d) { return d.x; }));
y.domain([0, d3.max(data, function(d) { return d.y; })]);

// update the data association with the path and recompute the area
svg.selectAll("path").data([data])
    .attr("d", area);

Et vous devriez mettre votre région à jour.

Vous pouvez l'essayer ici

La façon dont vos données sont organisées à l'aide des données jointes (au lieu de données) peut ne pas faire beaucoup de différence. Notez que ici l'élément de données (unique) que vous associez au chemin est la liste complète de coordonnées afin de mettre à jour la zone dont vous avez besoin de passer dans un nouvelle liste complète des coordonnées.

Si vous voulez vraiment minimiser le montant à redessiner, vous pouvez diviser la zone et dessiner chaque segment de ligne. Ensuite, vous revenez essentiellement à l'exemple de graphique à barres, mais avec des barres non plates et sans espacement.

19
Superboggly