web-dev-qa-db-fra.com

D3.js liant un objet aux données et ajoutant pour chaque clé

Je suis un débutant D3.js et j'apprends à jouer avec les données.

Disons que j'ai un objet avec des noms comme clés, et chaque clé a un tableau de nombres comme celui-ci:

var userdata = {
    'John' : [0, 1, 3, 9, 8, 7],
    'Harry': [0, 10, 7, 1, 1, 11],
    'Steve': [3, 1, 4, 4, 4, 17],
    'Adam' : [4, 77, 2, 13, 11, 13]
};

Pour chaque utilisateur, je voudrais ajouter un objet SVG, puis tracer la ligne avec le tableau de valeurs pour cet utilisateur.

Voici donc mon hypothèse sur la façon dont cela ressemblerait sur la base de tutoriels, mais je sais que c'est incorrect. Il s'agit de montrer mes connaissances limitées et de mieux comprendre ce que je fais:

Je dois d'abord créer la ligne

var line = d3.svg.line().interpolate('basis');

Ensuite, je veux lier les données à mon corps et ajouter un élément svg pour chaque clé:

d3.select('body')
    .selectAll('svg')
    .data(userdata)
    .enter()
    .append('svg')
    .append(line)
    .x(function(d, i) { return i; })
    .y(function(d) { return d[i]; });

Alors je suis proche ??

23
frshca

Voici un autre exemple similaire à celui de mbeasley: http://jsfiddle.net/2N2rt/15/ qui ajoute l'axe, les couleurs et retourne le graphique côté droit vers le haut. Tout d'abord, j'ai massé vos données un peu. Fonctionne mieux si vous avez un tableau de valeurs et que j'ai utilisé des clés pour faciliter l'accès aux propriétés name et values.

var data = [
    {name: 'John', values: [0,1,3,9, 8, 7]},
    {name: 'Harry', values: [0, 10, 7, 1, 1, 11]},
    {name: 'Steve', values: [3, 1, 4, 4, 4, 17]},
    {name: 'Adam', values: [4, 77, 2, 13, 11, 13]}
];

Généralement en d3 vous configurez le graphique comme celui-ci qui détermine la taille du graphique réel et les marges environnantes.

var margin = {top: 20, right: 80, bottom: 30, left: 50},
    width = 640 - margin.left - margin.right,
    height = 380 - margin.top - margin.bottom;

Ensuite, vous pouvez créer vos échelles en fonction de vos données. Bien que vous n'ayez pas à les créer, ils facilitent le positionnement des éléments sur le graphique en convertissant les valeurs en points. domain correspond aux valeurs min et max de vos données, tandis que range correspond aux valeurs min et max de la taille de votre graphique. Notez que le range pour le y axis est inversé, ce qui place (0,0) dans le coin inférieur gauche (généralement 0 pour l'axe y est en haut).

var x = d3.scale.linear()
    .domain([0, d3.max(data, function(d) { return d.values.length - 1; })])
    .range([0, width]);

var y = d3.scale.linear()
    .domain([d3.min(data, function(d) { return d3.min(d.values); }),
             d3.max(data, function(d) { return d3.max(d.values); })])
    .range([height, 0]);

d3 a quelques fonctionnalités pour créer automatiquement des échelles de couleurs pour vous. Il suffit de le configurer avec les touches que vous souhaitez utiliser et le nombre de couleurs (je pense qu'il y a 10 et 20 options de couleurs).

var color = d3.scale.category10()
    .domain(d3.keys(data[0]).filter(function(key) { return key === "name"; }));

Ici, nous utilisons nos échelles pour configurer les axes x et y. Il existe de nombreuses options différentes pour les axes. TickFormat est pratique pour changer l'apparence des tiques, d3.format dispose de nombreuses options différentes, de sorte que vous devez rarement créer un formateur personnalisé.

var xAxis = d3.svg.axis()
    .scale(x)
    .tickFormat(d3.format('d'))
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

Ici, nous créons une fonction réutilisable qui sait dessiner une ligne. Nous passerons chaque point de données pour chaque personne dans la fonction de ligne plus tard. Notez que d contient l'ensemble actuel de valeurs que nous représentons graphiquement et i est l'index des valeurs actuelles dans notre tableau de données d'origine.

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

Enfin, nous pouvons commencer à ajouter des éléments à notre graphique, en créant et en positionnant d'abord l'élément svg principal.

var svg = d3.select("#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 + ")");

Ensuite, en ajoutant chaque axe.

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis);

Nous ajoutons un groupe (g) pour chaque personne et associons les données au groupe. Nous utiliserons ces données lorsque nous tracerons les lignes. Nous fournissons un class pour que nous puissions styliser le graphique plus tard si nous le voulons.

  var people = svg.selectAll(".people")
      .data(data)
    .enter().append("g")
      .attr("class", "people");

Enfin, tracez les lignes pour chaque personne.

  people.append("path")
      .attr("class", "line")
      .attr("d", function(d) { return line(d.values); })
      .style("stroke", function(d) { return color(d.name); });

J'ai utilisé vos données pour répondre à une autre question sur le dessin d'une grille lorsque vous avez des valeurs négatives. Vous pouvez voir ce graphique sur http://jsfiddle.net/2y3er/2/ .

35
Bill

Je dirais que vous allez dans la bonne direction. Voici ce que je ferais (mais sachez qu'il n'y a pas qu'une seule façon de le faire):

// your user data
var userdata = {
    'John' : [0, 1, 3, 9, 8, 7],
    'Harry': [0, 10, 7, 1, 1, 11],
    'Steve': [3, 1, 4, 4, 4, 17],
    'Adam' : [4, 77, 2, 13, 11, 13]
}; 

// add your main SVG block
var svg = d3.select('body')
    .append('svg')
    .attr('width', 400)
    .attr('height', 200)
    .attr('id', 'chart');

// add an SVG group element for each user
var series = svg.selectAll('g.series')
    .data(d3.keys(userdata))
    .enter()
    .append('g')
    .attr('class', 'series');

// create your line generator
var line = d3.svg.line()
    .interpolate('basis')
    .x(function(d, i) {
        return i*40; // *40 just to increase the chart size
    })
    .y(function(d) {
        return d*3; // *3 for the same reason
    });

// add a line for each user using your SVG grouping 
var lineSVG = series.selectAll('.line')
    .data(d3.keys(userdata))
    .enter()
    .append('svg:path')
    .attr('d', function(d) {
        return line(userdata[d]);  
    })
    .attr('class','line');

Voici une démo du code ci-dessus.

Je vous recommande également fortement de lire cet article , car cela aide vraiment à solidifier le fonctionnement de d3.

11
mbeasley