40 votes

Dessiner 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 être 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 les 4.

Je peux faire quelque chose comme ça :

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 ensuite, ajoutez-les 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));

Existe-t-il un meilleur moyen, plus général, d'ajouter ces chemins ?

74voto

mbostock Points 25336

Oui. D'abord, je restructurerais vos données pour faciliter l'itération, 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 du chemin en une seule fois :

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

Si vous souhaitez réduire le format de la structure de données, vous pouvez également extraire les heures 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]
];

Comme la matrice n'inclut pas la valeur temporelle, vous devez la chercher dans l'accesseur x du générateur de lignes. D'autre part, l'accesseur y est simplifié puisque vous pouvez passer la valeur de la matrice directement à l'échelle y :

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

La création des éléments reste la même :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X