Ajouter Node à D3 Tree v4

J'utilise D3 v4 pour créer un arbre.

Fiddle: https://jsfiddle.net/a6pLqpxw/

J'essaie maintenant d'ajouter un support pour ajouter dynamiquement (et supprimer) des enfants à partir d'un nœud sélectionné.

Cependant, je ne peux pas redessiner le graphique sans avoir à effectuer un redessin complet. J'ai modifié le code à partir du code du diagramme de l'arbre pliable à l' adresse suivante : https://bl.ocks.org/d3noob/43a860bc0024792f8803bba8ca0d5ecd

Plus précisément, le bloc suivant n'effectue pas un nouveau calcul de la mise en page pour ses enfants.

document.getElementById('add-child').onclick = function() { console.log(selected); selected.children.push({ type: 'resource-delete', name: new Date().getTime(), attributes: [], children: [] }); update(selected); }; 

Est-ce que quelqu'un a de bons exemples d'ajout ou de suppression dynamique des noeuds dans les arborescences dans D3.js v4?

J'ai trouvé cette solution pour ajouter un nouveau nœud de manière dynamique à D3 Tree v4. .

L'arbre D3 v4 nécessite des noeuds.

Créez des nœuds à partir de vos données arborescentes (json) en utilisant d3.hierarchy(..) et l'a parent.children dans parent.children array et mettez à jour l'arborescence.

Extrait de code

 //Adding a new node (as a child) to selected Node (code snippet) var newNode = { type: 'node-type', name: new Date().getTime(), children: [] }; //Creates a Node from newNode object using d3.hierarchy(.) var newNode = d3.hierarchy(newNode); //later added some properties to Node like child,parent,depth newNode.depth = selected.depth + 1; newNode.height = selected.height - 1; newNode.parent = selected; newNode.id = Date.now(); //Selected is a node, to which we are adding the new node as a child //If no child array, create an empty array if(!selected.children){ selected.children = []; selected.data.children = []; } //Push it to parent.children array selected.children.push(newNode); selected.data.children.push(newNode.data); //Update tree update(selected); 

Violon


 // ### DATA MODEL START var data = { type: 'action', name: '1', attributes: [], children: [{ type: 'children', name: '2', attributes: [{ 'source-type-property-value': 'streetlight' }], children: [{ type: 'parents', name: '3', attributes: [{ 'source-type-property-value': 'cable' }], children: [{ type: 'resource-delete', name: '4', attributes: [], children: [] }] }, { type: 'children', name: '5', attributes: [{ 'source-type-property-value': 'lantern' }], children: [] }] }] }; // ### DATA MODEL END // Set the dimensions and margins of the diagram var margin = {top: 20, right: 90, bottom: 30, left: 90}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; // append the svg object to the body of the page // appends a 'group' element to 'svg' // moves the 'group' element to the top left margin var svg = d3.select("body"). append("svg"). attr("width", width + margin.right + margin.left). attr("height", height + margin.top + margin.bottom). append("g"). attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var i = 0, duration = 750, root; // declares a tree layout and assigns the size var treemap = d3.tree().size([height, width]); // Assigns parent, children, height, depth root = d3.hierarchy(data, function(d) { return d.children; }); root.x0 = height / 2; root.y0 = 0; update(root); var selected = null; function update(source) { // Assigns the x and y position for the nodes var treeData = treemap(root); // Compute the new tree layout. var nodes = treeData.descendants(), links = treeData.descendants().slice(1); // Normalize for fixed-depth. nodes.forEach(function(d){ dy = d.depth * 180 }); // ### LINKS // Update the links... var link = svg.selectAll('line.link'). data(links, function(d) { return d.id; }); // Enter any new links at the parent's previous position. var linkEnter = link.enter(). append('line'). attr("class", "link"). attr("stroke-width", 2). attr("stroke", 'black'). attr('x1', function(d) { return source.y0; }). attr('y1', function(d) { return source.x0; }). attr('x2', function(d) { return source.y0; }). attr('y2', function(d) { return source.x0; }); var linkUpdate = linkEnter.merge(link); linkUpdate.transition(). duration(duration). attr('x1', function(d) { return d.parent.y; }). attr('y1', function(d) { return d.parent.x; }). attr('x2', function(d) { return dy; }). attr('y2', function(d) { return dx; }); // Transition back to the parent element position linkUpdate.transition(). duration(duration). attr('x1', function(d) { return d.parent.y; }). attr('y1', function(d) { return d.parent.x; }). attr('x2', function(d) { return dy; }). attr('y2', function(d) { return dx; }); // Remove any exiting links var linkExit = link.exit(). transition(). duration(duration). attr('x1', function(d) { return source.x; }). attr('y1', function(d) { return source.y; }). attr('x2', function(d) { return source.x; }). attr('y2', function(d) { return source.y; }). remove(); // ### CIRCLES // Update the nodes... var node = svg.selectAll('g.node') .data(nodes, function(d) { return d.id || (d.id = ++i); }); // Enter any new modes at the parent's previous position. var nodeEnter = node.enter(). append('g'). attr('class', 'node'). attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; }). on('click', click); // Add Circle for the nodes nodeEnter.append('circle'). attr('class', 'node'). attr('r', 25). style("fill", function(d) { return "#0e4677"; }); // Update var nodeUpdate = nodeEnter.merge(node); // Transition to the proper position for the node nodeUpdate.transition(). duration(duration). attr("transform", function(d) { return "translate(" + dy + "," + dx + ")"; }); // Update the node attributes and style nodeUpdate.select('circle.node'). attr('r', 25). style("fill", function(d) { return "#0e4677"; }). attr('cursor', 'pointer'); // Remove any exiting nodes var nodeExit = node.exit(). transition(). duration(duration). attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; }). remove(); // On exit reduce the node circles size to 0 nodeExit.select('circle').attr('r', 0); // Store the old positions for transition. nodes.forEach(function(d){ d.x0 = dx; d.y0 = dy; }); // Toggle children on click. function click(d) { selected = d; document.getElementById('add-child').disabled = false; document.getElementById('remove').disabled = false; update(d); } } document.getElementById('add-child').onclick = function() { //creates New OBJECT var newNodeObj = { type: 'resource-delete', name: new Date().getTime(), attributes: [], children: [] }; //Creates new Node var newNode = d3.hierarchy(newNodeObj); newNode.depth = selected.depth + 1; newNode.height = selected.height - 1; newNode.parent = selected; newNode.id = Date.now(); if(!selected.children){ selected.children = []; selected.data.children = []; } selected.children.push(newNode); selected.data.children.push(newNode.data); update(selected); }; 
 <script src="https://d3js.org/d3.v4.min.js"></script> <button id="add-child" disabled="disabled">Add Child</button>