web-dev-qa-db-fra.com

d3.js comment ajouter dynamiquement des nœuds à un arbre

J'utilise un arbre d3.js et je voudrais ajouter des nœuds de manière dynamique, plutôt que de pré-charger l'arbre entier.

Comment modifier ce qui suit afin d'ajouter dynamiquement des nœuds JSON supplémentaires lorsqu'un nœud est cliqué? (voir lien ci-dessous et code ci-dessous)

http://mbostock.github.com/d3/talk/20111018/tree.html

Ainsi, plutôt que de pré-charger l'arborescence entière, je voudrais plutôt récupérer les nœuds enfants uniquement lorsque le parent est cliqué. Je peux récupérer le json pour les nœuds enfants dans la fonction bascule, mais je ne peux pas comprendre comment je peux les ajouter à l'arborescence.

var m = [20, 120, 20, 120],
    w = 1280 - m[1] - m[3],
    h = 800 - m[0] - m[2],
    i = 0,
    root;

var tree = d3.layout.tree()
    .size([h, w]);

var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.y, d.x]; });

var vis = d3.select("#body").append("svg:svg")
    .attr("width", w + m[1] + m[3])
    .attr("height", h + m[0] + m[2])
  .append("svg:g")
    .attr("transform", "translate(" + m[3] + "," + m[0] + ")");

d3.json("flare.json", function(json) {
  root = json;
  root.x0 = h / 2;
  root.y0 = 0;

  function toggleAll(d) {
    if (d.children) {
      d.children.forEach(toggleAll);
      toggle(d);
    }
  }

  // Initialize the display to show a few nodes.
  root.children.forEach(toggleAll);
  toggle(root.children[1]);
  toggle(root.children[1].children[2]);
  toggle(root.children[9]);
  toggle(root.children[9].children[0]);

  update(root);
});

function update(source) {
  var duration = d3.event && d3.event.altKey ? 5000 : 500;

  // Compute the new tree layout.
  var nodes = tree.nodes(root).reverse();

  // Normalize for fixed-depth.
  nodes.forEach(function(d) { d.y = d.depth * 180; });

  // Update the nodes…
  var node = vis.selectAll("g.node")
      .data(nodes, function(d) { return d.id || (d.id = ++i); });

  // Enter any new nodes at the parent's previous position.
  var nodeEnter = node.enter().append("svg:g")
      .attr("class", "node")
      .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
      .on("click", function(d) { toggle(d); update(d); });

  nodeEnter.append("svg:circle")
      .attr("r", 1e-6)
      .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

  nodeEnter.append("svg:text")
      .attr("x", function(d) { return d.children || d._children ? -10 : 10; })
      .attr("dy", ".35em")
      .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
      .text(function(d) { return d.name; })
      .style("fill-opacity", 1e-6);

  // Transition nodes to their new position.
  var nodeUpdate = node.transition()
      .duration(duration)
      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });

  nodeUpdate.select("circle")
      .attr("r", 4.5)
      .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

  nodeUpdate.select("text")
      .style("fill-opacity", 1);

  // Transition exiting nodes to the parent's new position.
  var nodeExit = node.exit().transition()
      .duration(duration)
      .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
      .remove();

  nodeExit.select("circle")
      .attr("r", 1e-6);

  nodeExit.select("text")
      .style("fill-opacity", 1e-6);

  // Update the links…
  var link = vis.selectAll("path.link")
      .data(tree.links(nodes), function(d) { return d.target.id; });

  // Enter any new links at the parent's previous position.
  link.enter().insert("svg:path", "g")
      .attr("class", "link")
      .attr("d", function(d) {
        var o = {x: source.x0, y: source.y0};
        return diagonal({source: o, target: o});
      })
    .transition()
      .duration(duration)
      .attr("d", diagonal);

  // Transition links to their new position.
  link.transition()
      .duration(duration)
      .attr("d", diagonal);

  // Transition exiting nodes to the parent's new position.
  link.exit().transition()
      .duration(duration)
      .attr("d", function(d) {
        var o = {x: source.x, y: source.y};
        return diagonal({source: o, target: o});
      })
      .remove();

  // Stash the old positions for transition.
  nodes.forEach(function(d) {
    d.x0 = d.x;
    d.y0 = d.y;
  });
}

// Toggle children.
function toggle(d) {

  // I could retrieve the child nodes here, but how to add them to the tree?

  if (d.children) {
    d._children = d.children;
    d.children = null;
  } else {
    d.children = d._children;
    d._children = null;
  }
}
31
Mike Mike

J'ai pu ajouter dynamiquement des nœuds en ajoutant le code suivant dans la fonction bascule:

$.getJSON(addthese.json, function(addTheseJSON) {
    var newnodes = tree.nodes(addTheseJSON.children).reverse();
    d.children = newnodes[0];
    update(d);
});

Notes: J'utilise jQuery pour récupérer le fichier json

24
Mike Mike

Je suis nouveau sur D3, mais ce code brut pourrait être utile. Vous pouvez créer un objet JSON et le pousser dans l'arborescence/le lien. Ensuite, il ne s'agit que de redessiner l'arbre.

function createTreeNode(source){

var current_node = tree.nodes(source);
var myJSONObject = {"name": "new Node","children": []}; 

if(current_node[0]._children!=null){
current_node[0]._children.Push(myJSONObject);
console.log(current_node[0]._children);
source.children = source._children;
source._children = null;
}

else if(current_node[0].children!=null && current_node[0]._children!=null){
current_node[0].children.Push(myJSONObject);
console.log(current_node[0].children);
}

else{
current_node[0].children=[]
current_node[0].children.Push(myJSONObject);
console.log(current_node[0].children);
}

tree.links(current_node).Push(current_node[current_node.length-1]);
navigate_tree(source);}
0
user2188329