2013-07-02 6 views
1

Récemment, j'ai essayé de maîtriser la bibliothèque d3js (ce qui est génial) et j'essaie de faire les choses les plus simples mais pour une raison quelconque cela ne fonctionne pas correctement. J'ai regardé des problèmes connexes mais aucun n'a pu m'aider à trouver mon problème.Ajouter un nœud sur un autre nœud avec d3js

La configuration est simple, j'ai une disposition de force avec un seul nœud et aucun lien. Lorsque l'utilisateur clique sur ce nœud, je voudrais ajouter un nouveau nœud qui est lié au nœud sur lequel on a cliqué. Voici mon code jusqu'à présent. Le premier noeud ajouté a une position très aléatoire et après cela je garde un message "Uncaught TypeError: Impossible de lire la propriété '__data__' de null".

Nous vous remercions de votre aide!

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="utf-8"> 
    <title>D3 test</title> 
</head> 
<body> 
    <div id="viz"> 
    </div> 
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> 
    <script type="text/javascript"> 
     var w = 800; 
     var h = 800; 
     var padding = 100; 
     var svg = d3.select("#viz") 
        .append("svg") 
        .attr("width", w) 
        .attr("height", h); 
     var nodes = [{name:"n0"}]; 
     var links = []; 
     var force = d3.layout.force() 
         .size([w, h]) 
         .linkDistance([100]) 
         .charge([-30]) 
         .start(); 
     var link = svg.selectAll(".link"), 
      node = svg.selectAll(".node"); 

     update(); 

     function update() { 
      force.nodes(nodes) 
        .links(links) 
        .start(); 
      link = link.data(force.links(), function(d) {return d.source.name + "-" + d.target.name;}) 
          .enter() 
          .insert("line", ".node") 
          .attr("class", "link") 
          .style("stroke", "red") 
          .style("stroke-width", 2); 

      node = node.data(force.nodes(), function(d) {return d.name;}) 
          .enter() 
          .append("circle") 
          .attr("class", "node") 
          .attr("r", 10) 
          .style("fill", "black") 
          .on("click", function(d) { 
           var n = {name:"n"+nodes.length}; 
           nodes.push(n); 
           links.push({source:d, target:n}); 
           update(); 
          }) 
          .call(force.drag); 
     } 
     force.on("tick", function() { 
      link.attr("x1", function(d) {return d.source.x;}) 
        .attr("y1", function(d) {return d.source.y;}) 
        .attr("x2", function(d) {return d.target.x;}) 
        .attr("y2", function(d) {return d.target.y;}); 
      node.attr("cx", function(d) {return d.x}) 
        .attr("cy", function(d) {return d.y}); 
     }); 
    </script> 
</body> 

+3

[Cet exemple] (http://bl.ocks.org/benzguo/4370043) fait presque exactement ce que vous voulez. D'une manière générale, la disposition des forces n'est pas la meilleure façon de commencer avec D3. S'en tenir aux choses faciles d'abord :) –

+0

Ok merci pour le conseil! Je peux voir pourquoi votre exemple fonctionne, je ne peux toujours pas voir ce qui est défectueux dans le mien si ... Si vous avez une idée que j'aimerais savoir parce que ça me dérange vraiment :) –

Répondre

2

Pour une raison que je ne peux pas expliquer, il fonctionne parfaitement quand je change ce bit

node = node.data(force.nodes(), function(d) {return d.name;}).enter()... 

à cette

node = node.data(force.nodes(), function(d) {return d.name;}) 
node.enter()... 

Et faire la même chose à la sélection "lien"

Je suppose que cela a à voir avec entrer sélections et co.

+4

La raison en est que, dans «tick», avec Dans la première version, vous utilisez la sélection entrée (nouveaux nœuds uniquement) alors que sur la deuxième version, vous utilisez la sélection complète (tous les nœuds). –

Questions connexes