Dessin de plusieurs lignes en D3.js

jusqu'à présent, j'ai utilisé des boucles pour ajouter des éléments de ligne à une visualisation D3, mais cela ne semble pas dans l'esprit de l'API.

disons que j'ai des données,

var data = {time: 1, value: 2, value2: 5, value3: 3,value4: 2},
           {time: 2, value: 4, value2: 9, value3: 2,value4: 4},
           {time: 3, value: 8, value2:12, value3: 2,value4:15}]);

je voudrais quatre lignes, avec le temps comme X pour tous les 4.

je peux faire quelque chose comme ceci:

var l = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[1]]);})
        .interpolate("basis");
var l2 = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[2]]);})
        .interpolate("basis");
var l3 = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[3]]);})
        .interpolate("basis");  
var l4 = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[4]]);})
        .interpolate("basis");

Et puis les ajouter un par un (ou par une boucle).

var line1 = group.selectAll("path.path1")
        .attr("d",l(data));
var line2 = group.selectAll("path.path2")
        .attr("d",l2(data));
var line3 = group.selectAll("path.path3")
        .attr("d",l3(data));
var line4 = group.selectAll("path.path4")
        .attr("d",l4(data));

y a-t-il une meilleure façon générale d'ajouter ces chemins?

38
demandé sur VividD 2011-12-31 21:27:08

1 réponses

Oui. Tout d'abord, je restructurerais vos données pour une itération plus facile, comme ceci:

var series = [
  [{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 8}],
  [{time: 1, value: 5}, {time: 2, value: 9}, {time: 3, value: 12}],
  [{time: 1, value: 3}, {time: 2, value: 2}, {time: 3, value: 2}],
  [{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 15}]
];

Maintenant, vous n'avez besoin que d'une seule ligne générique:

var line = d3.svg.line()
    .interpolate("basis")
    .x(function(d) { return x(d.time); })
    .y(function(d) { return y(d.value); });

, Et vous pouvez ensuite ajouter tous les éléments de chemin d'accès en une seule fois:

group.selectAll(".line")
    .data(series)
  .enter().append("path")
    .attr("class", "line")
    .attr("d", line);

si vous voulez rendre le format de structure de données plus petit, vous pouvez aussi extraire les temps dans un tableau séparé, puis utiliser un tableau 2D pour les valeurs. Cela ressemblerait à ceci:

var times = [1, 2, 3];

var values = [
  [2, 4, 8],
  [5, 9, 12],
  [3, 2, 2],
  [2, 4, 15]
];

puisque la matrice ne incluez la valeur de temps, vous devez le chercher à partir du X-accessor du générateur de ligne. D'un autre côté, l'accesseur en y est simplifié puisque vous pouvez passer la valeur de la matrice directement à l'échelle en y:

var line = d3.svg.line()
    .interpolate("basis")
    .x(function(d, i) { return x(times[i]); })
    .y(y);

Création d'éléments reste le même:

group.selectAll(".line")
    .data(values)
  .enter().append("path")
    .attr("class", "line")
    .attr("d", line);
73
répondu mbostock 2012-01-04 16:41:34