2016-06-24 10 views
3

Ich habe versucht, eine zusammenklappbare Kraft Layout mit d3js v4, ähnlich wie diese zu erstellen: https://mbostock.github.io/d3/talk/20111116/force-collapsible.htmlRecreating zusammenklappbar Kraft Layout mit d3 v4

Ich habe in der Lage, das Layout selbst zu erstellen. Aber nicht in der Lage, es zu aktualisieren. Kann jemand helfen?

Hier ist mein js Code:

var width = 960, 
 
    height = 600; 
 

 
var root = { 
 
\t "name": "server1900", 
 
\t "children": [{ 
 
\t \t "name": "server913", 
 
\t \t "_children": null, 
 
\t \t "children": [{ 
 
\t \t \t "name": "server948" 
 
\t \t }, { 
 
\t \t \t "name": "server946" 
 
\t \t }] 
 
\t }, { 
 
\t \t "name": "server912", 
 
\t \t "_children": null, 
 
\t \t "children": [{ 
 
\t \t \t "name": "server984" 
 
\t \t }, { 
 
\t \t \t "name": "server983" 
 
\t \t }] 
 
\t }, { 
 
\t \t "name": "server911", 
 
\t \t "_children": null, 
 
\t \t "children": [{ 
 
\t \t \t "name": "server999", 
 
\t \t \t "_children": null, 
 
\t \t \t "children": [{ 
 
\t \t \t \t "name": "server992" 
 
\t \t \t }] 
 
\t \t }] 
 
\t }] 
 
}; 
 

 
root = d3.hierarchy(root); 
 

 
var i = 0; 
 

 
var transform = d3.zoomIdentity;; 
 

 
var nodeSvg, linkSvg, simulation, nodeEnter, linkEnter ; 
 

 
var svg = d3.select("body").append("svg") 
 
    .attr("width", width) 
 
    .attr("height", height) 
 
    .call(d3.zoom().scaleExtent([1/2, 8]).on("zoom", zoomed)) 
 
    .append("g") 
 
    .attr("transform", "translate(40,0)"); 
 

 
function zoomed() { 
 
    svg.attr("transform", d3.event.transform); 
 
} 
 

 
simulation = d3.forceSimulation() 
 
    .force("link", d3.forceLink().id(function(d) { return d.id; })) 
 
    .force("charge", d3.forceManyBody()) 
 
    .force("center", d3.forceCenter(width/2, height/2)) 
 
    .on("tick", ticked); 
 

 
update(); 
 

 
function update() { 
 
    var nodes = flatten(root); 
 
    var links = root.links(); 
 

 
    simulation 
 
    .nodes(nodes) 
 

 
    simulation.force("link") 
 
    .links(links); 
 

 
    linkSvg = svg.selectAll(".link") 
 
    .data(links, function(d) { return d.target.id; }) 
 

 
    linkSvg.exit().remove(); 
 

 
    linkSvg = linkSvg.enter() 
 
     .append("line") 
 
     .attr("class", "link"); 
 

 
    nodeSvg = svg.selectAll(".node") 
 
    .data(nodes, function(d) { return d.id; }) 
 

 
    nodeSvg.exit().remove(); 
 

 
    nodeSvg = nodeSvg.enter() 
 
    .append("g") 
 
     .attr("class", "node") 
 
     .on("click", click) 
 
     .call(d3.drag() 
 
     .on("start", dragstarted) 
 
     .on("drag", dragged) 
 
     .on("end", dragended)) 
 

 
    nodeSvg.append("circle") 
 
     .attr("r", 4 ) 
 
     .append("title") 
 
     .text(function(d) { return d.data.name; }) 
 

 
    nodeSvg.append("text") 
 
     .attr("dy", 3) 
 
     .attr("x", function(d) { return d.children ? -8 : 8; }) 
 
     .style("text-anchor", function(d) { return d.children ? "end" : "start"; }) 
 
     .text(function(d) { return d.data.name; }); 
 

 

 

 
} 
 

 
function ticked() { 
 
    linkSvg 
 
     .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; }); 
 

 
    nodeSvg 
 
     .attr("transform", function(d) { return "translate(" + d.x + ", " + d.y + ")"; }); 
 
} 
 

 
function click(d) { 
 
\t if (d.children) { 
 
\t \t d._children = d.children; 
 
\t \t d.children = null; 
 
    update(); 
 
    simulation.restart(); 
 
\t } else { 
 
\t \t d.children = d._children; 
 
\t \t d._children = null; 
 
    update(); 
 
    simulation.restart(); 
 
\t } 
 
} 
 

 
function dragstarted(d) { 
 
    if (!d3.event.active) simulation.alphaTarget(0.3).restart() 
 
    simulation.fix(d); 
 
} 
 

 
function dragged(d) { 
 
    simulation.fix(d, d3.event.x, d3.event.y); 
 
} 
 

 
function dragended(d) { 
 
    if (!d3.event.active) simulation.alphaTarget(0); 
 
    simulation.unfix(d); 
 
} 
 

 
function flatten (root) { 
 
    // hierarchical data to flat data for force layout 
 
    var nodes = []; 
 
    function recurse(node) { 
 
    if (node.children) node.children.forEach(recurse); 
 
    if (!node.id) node.id = ++i; 
 
    else ++i; 
 
    nodes.push(node); 
 
    } 
 
    recurse(root); 
 
    return nodes; 
 
}
line { 
 
    stroke: #666; 
 
} 
 

 
.node { 
 
    pointer-events: all; 
 
} 
 

 
circle { 
 
    stroke: none; 
 
    stroke-width: 40px; 
 
} 
 

 
.node text { 
 
    font: 8px sans-serif; 
 
}
<script src="https://d3js.org/d3.v4.0.0-alpha.50.min.js"></script>

Hier ist meine Geige. https://jsfiddle.net/t4vzg650/4/

Dank

+0

Welche Update soll das heißen? Gibt es Fehler oder zeigt es nicht das gewünschte Verhalten? – altocumulus

+0

@altocumulus Nachdem ein Knoten auf einen Knoten geklickt hat, werden die untergeordneten Knoten ein-/ausgeblendet, d. H. Die Karte wird aktualisiert, um neue Knoten anzuzeigen/auszublenden. Ich meine, das hat Update. Keine Fehler. Nicht das gewünschte Verhalten zeigen. – kirupakaranh

+0

Sind Sie sicher, dass diese d3.version.alpha keine Fehler enthält? – Klaujesi

Antwort

5

habe ich vergessen, alte Knoten nach fusionieren() eingeben.

Danke an Mike Bostock für die Hilfe bei diesem Problem. Ich dachte, es gab ein Problem mit d3 v4, stellt sich heraus, ich habe Änderungen nicht vollständig gelesen: |

Siehe diese für weitere Informationen: https://github.com/d3/d3-force/issues/37

Fest Geige: https://jsfiddle.net/t4vzg650/6/

+1

Große Hilfe. Für jeden anderen, der sich damit beschäftigt, kann es auch nützlich sein, die Schlüsselfunktion (https://bost.ocks.org/mike/constancy/#key-functions) zu verwenden, die der @ kirupakaranh (korrekt) verwendet hat: 'Funktion (d) {return d.id; } '. Viele bewegliche Teile und die Schlüsselfunktion zusätzlich zum Zusammenführen lösten mein Problem. – ibgib

Verwandte Themen