2016-07-04 2 views
4

Ich habe vor kurzem meine erste Kraft gerichtete Grafik mit v3-Bibliothek erstellt, aber jetzt muss ich das gleiche Diagramm mit D3 Version 4-Bibliothek erstellen, aber die Methoden haben sich in v4 enorm verändert, und jetzt bekomme ich Fehler bei Alle force()/drag() Methoden von 3, die jetzt nicht in v4 existieren.Probleme beim Konvertieren eines D3 v3 Force-gerichteten Graphen in D3 v4-Bibliotheksimplementierung?

Mein Diagramm basiert auf folgenden Mockup - http://www.ourd3js.com/wordpress/?p=606

Gibt es eine Sammlung von Proben, die in v4 Bibliothek von d3 irgendwo erstellt wurden, wo ich einen Blick nehmen und einige Funktionen lernen, die ich mit für diese ersetzen kann bestimmtes Diagramm?

EDIT:

Meine aktuellen Code sieht wie folgt aus, aber ich bin nicht in der Lage es vollständig zu konvertieren, zum Beispiel, sind die Knotenverbindungen sehr nah manchmal, dass der Text von Verbindungen und Knoten überlappt.

<svg width="960" height="600"></svg> 

Javascript-Code:

var svg = d3.select("svg"), 
    width = +svg.attr("width"), 
    height = +svg.attr("height"); 

var graph = root; 

var w = window, 
    d = document, 
    e = d.documentElement, 
    g = d.getElementsByTagName('body')[0], 
    x = w.innerWidth || e.clientWidth || g.clientWidth, 
    y = w.innerHeight|| e.clientHeight|| g.clientHeight; 

var width = x; 
var height = y; 
var img_w = 24; 
var img_h = 24; 
var k = Math.sqrt(root.nodes.length/(width * height)); 

var simulation = d3.forceSimulation() 
    .force("link", d3.forceLink().id(function(d) { return d.id; })) 
    .force("charge", d3.forceManyBody().strength(-5/k)) 
    .force("center", d3.forceCenter(width/2, height/2)); 

    var link = svg.append("g") 
       .attr("class", "links") 
       .selectAll("line") 
       .data(graph.links) 
       .enter().append("line"); 

    var node = svg.append("g") 
        .attr("class", "nodes") 
        .selectAll("circle") 
        .data(graph.nodes) 
        .enter().append("image") 
          .attr("width",img_w) 
          .attr("height",img_h) 
          .attr("xlink:href",function(d){ 
           return d.image; 
          }) 
          .call(d3.drag() 
        .on("start", dragstarted) 
        .on("drag", dragged) 
        .on("end", dragended)); 

    var links_text = svg.selectAll(".linetext") 
         .data(graph.links) 
         .enter() 
         .append("text") 
         .attr("class","linetext slds-text-heading--small") 
         .attr("text-anchor", "middle") 
         .text(function(d){ 
          return '['+d.relation+']'; 
         }); 

    var nodes_text = svg.selectAll(".nodetext") 
         .data(graph.nodes) 
         .enter() 
         .append("text") 
         .attr("class","nodetext slds-text-heading--label") 
         .attr("text-anchor", "middle") 
         .attr("dx",-20) 
         .attr("dy",20) 
         .text(function(d){ 
          return (d.subname!=''?(d.subname+': '):'')+d.name; 
         }); 

    simulation 
     .nodes(graph.nodes) 
     .on("tick", ticked); 

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

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

    links_text 
     .attr("x",function(d){ return (d.source.x + d.target.x)/2; }) 
     .attr("y",function(d){ return (d.source.y + d.target.y)/2; }); 

    node 
     .attr("x", function(d) { return d.x; }) 
     .attr("y", function(d) { return d.y; }); 

    nodes_text 
     .attr("x",function(d){ return d.x + 20 }) 
     .attr("y",function(d){ return d.y + img_w/2; }); 
    } 


function dragstarted(d) { 
    if (!d3.event.active) simulation.alphaTarget(0.3).restart(); 
    d.fx = d.x; 
    d.fy = d.y; 
} 

function dragged(d) { 
    d.fx = d3.event.x; 
    d.fy = d3.event.y; 
} 

function dragended(d) { 
    if (!d3.event.active) simulation.alphaTarget(0); 
    d.fx = null; 
    d.fy = null; 
} 

Die JSON Datenstring:

var root = { 
    "nodes" : [ { 
    "subname" : "", 
    "name" : "Telco Power Case", 
    "image" : "/node32.png", 
    "id" : 0 
    }, { 
    "subname" : "Contact", 
    "name" : "Suman Kumar", 
    "image" : "/subnode32.png.png", 
    "id" : 1 
    }, { 
    "subname" : "Contact", 
    "name" : "Karla Samuel", 
    "image" : "/subnode32.png.png", 
    "id" : 2 
    }, { 
    "subname" : "Account", 
    "name" : "Signa Tech", 
    "image" : "/subnode32.png.png", 
    "id" : 3 
    }, { 
    "subname" : "", 
    "name" : "Maven's Case", 
    "image" : "/node32.png", 
    "id" : 4 
    }, { 
    "subname" : "", 
    "name" : "Delta Case", 
    "image" : "/node32.png", 
    "id" : 5 
    }, { 
    "subname" : "Contact", 
    "name" : "T Browney", 
    "image" : "/subnode32.png.png", 
    "id" : 6 
    }, { 
    "subname" : "Account", 
    "name" : "Presto", 
    "image" : "/subnode32.png.png", 
    "id" : 7 
    }, { 
    "subname" : "Contact", 
    "name" : "Bob Tannenbaum", 
    "image" : "/subnode32.png.png", 
    "id" : 8 
    }, { 
    "subname" : "Account", 
    "name" : "Tesla Power", 
    "image" : "/subnode32.png.png", 
    "id" : 9 
    } ], 
    "links" : [ { 
    "target" : 1, 
    "source" : 0, 
    "relation" : "Trainee" 
    }, { 
    "target" : 2, 
    "source" : 0, 
    "relation" : "Manager" 
    }, { 
    "target" : 3, 
    "source" : 0, 
    "relation" : "Technology" 
    }, { 
    "target" : 1, 
    "source" : 0, 
    "relation" : "Trainee" 
    }, { 
    "target" : 2, 
    "source" : 0, 
    "relation" : "Manager" 
    }, { 
    "target" : 3, 
    "source" : 0, 
    "relation" : "Technology" 
    }, { 
    "target" : 2, 
    "source" : 4, 
    "relation" : "Expert" 
    }, { 
    "target" : 2, 
    "source" : 5, 
    "relation" : "Expert" 
    }, { 
    "target" : 1, 
    "source" : 5, 
    "relation" : "Expert" 
    }, { 
    "target" : 6, 
    "source" : 5, 
    "relation" : "Trainee" 
    }, { 
    "target" : 7, 
    "source" : 5, 
    "relation" : "Technology;New Firm" 
    }, { 
    "target" : 8, 
    "source" : 4, 
    "relation" : "Expert" 
    }, { 
    "target" : 9, 
    "source" : 4, 
    "relation" : "New Firm" 
    }, { 
    "target" : 8, 
    "source" : 4, 
    "relation" : "Expert" 
    }, { 
    "target" : 9, 
    "source" : 4, 
    "relation" : "New Firm" 
    }, { 
    "target" : 6, 
    "source" : 5, 
    "relation" : "Trainee" 
    }, { 
    "target" : 7, 
    "source" : 5, 
    "relation" : "Technology;New Firm" 
    } ] 
}; 
+0

die einzige w: einige Korrekturen zu implementieren habe begonnen ay jemand kann Ihnen helfen, sieht Ihren Code ... –

+0

sry, ich habe gerade die Frage mit meinem Satz von Code aktualisiert. Ich habe bereits versucht, es basierend auf D3 Version 4 Funktionen zu ändern, aber ich bin nicht in der Lage, es genau zu arbeiten. Derzeit sind Knoten und Text irgendwie überlappend. Ich bin nicht in der Lage, eine feste Verbindung/Kantenlänge zwischen Knoten bereitzustellen, die ich mit der v3 linkDistance-Funktion bereitstellen könnte. – VarunC

+0

Ich versuche, diesem Beispiel zu folgen - http://bl.ocks.org/mbostock/2675ff61ea5e063ede2b5d63c08020c7, und ich bin nicht in der Lage, meine Image-Knoten auch zwischen zwei Kanten zu zentrieren. Derzeit beginnt die Bildplatzierung am Anfang eines Edge/Links. – VarunC

Antwort

5

Du eine Flut von Fragen auf einmal zu fragen, so lasst uns hol ein bisschen sani ty auf diese Frage.

Erstens ist die linkDistance jetzt distance auf dem d3.forceLink, so im Code:

.force("link", d3.forceLink().id(function(d) { return d.id; }).distance(200)) 

Zweitens Ihr Bild zu zentrieren, dies zu tun, wenn Sie es x-Position gesetzt:

node 
    .attr("x", function(d) { 
    return (d.x - img_w /2); 
    }); 

Drittens, um Grenzerkennung zu tun, müssen Sie dies selbst implementieren. Zum Beispiel fixieren die Knoten Position (Gebäude am letzten Code-Snippet) sein würde:

node 
    .attr("x", function(d) { 
    var xPos = (d.x - img_w /2); 
    if (xPos < 0) return 0; 
    if (xPos > (960 - img_w)) return (960 - img_w); 
    return xPos; 
    }) 
    .attr("y", function(d) { 
    var yPos = d.y; 
    if (yPos < 0) return 0; 
    if (yPos > (600 - img_h)) return (600 - img_h); 
    return yPos; 
    }); 

nun die gleiche Methodik auf die Links gelten ...


Hier einige Beispiel-Code, wo ich

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script> 
 
    <style> 
 
    .links line { 
 
     stroke: #aaa; 
 
    } 
 
    
 
    .nodes circle { 
 
     pointer-events: all; 
 
     stroke: none; 
 
     stroke-width: 40px; 
 
    } 
 
    </style> 
 
</head> 
 

 
<body> 
 
    <svg width="960" height="600"></svg> 
 
    <script> 
 
    var root = { 
 
     "nodes": [{ 
 
     "subname": "", 
 
     "name": "Telco Power Case", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 0 
 
     }, { 
 
     "subname": "Contact", 
 
     "name": "Suman Kumar", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 1 
 
     }, { 
 
     "subname": "Contact", 
 
     "name": "Karla Samuel", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 2 
 
     }, { 
 
     "subname": "Account", 
 
     "name": "Signa Tech", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 3 
 
     }, { 
 
     "subname": "", 
 
     "name": "Maven's Case", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 4 
 
     }, { 
 
     "subname": "", 
 
     "name": "Delta Case", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 5 
 
     }, { 
 
     "subname": "Contact", 
 
     "name": "T Browney", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 6 
 
     }, { 
 
     "subname": "Account", 
 
     "name": "Presto", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 7 
 
     }, { 
 
     "subname": "Contact", 
 
     "name": "Bob Tannenbaum", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 8 
 
     }, { 
 
     "subname": "Account", 
 
     "name": "Tesla Power", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 9 
 
     }], 
 
     "links": [{ 
 
     "target": 1, 
 
     "source": 0, 
 
     "relation": "Trainee" 
 
     }, { 
 
     "target": 2, 
 
     "source": 0, 
 
     "relation": "Manager" 
 
     }, { 
 
     "target": 3, 
 
     "source": 0, 
 
     "relation": "Technology" 
 
     }, { 
 
     "target": 1, 
 
     "source": 0, 
 
     "relation": "Trainee" 
 
     }, { 
 
     "target": 2, 
 
     "source": 0, 
 
     "relation": "Manager" 
 
     }, { 
 
     "target": 3, 
 
     "source": 0, 
 
     "relation": "Technology" 
 
     }, { 
 
     "target": 2, 
 
     "source": 4, 
 
     "relation": "Expert" 
 
     }, { 
 
     "target": 2, 
 
     "source": 5, 
 
     "relation": "Expert" 
 
     }, { 
 
     "target": 1, 
 
     "source": 5, 
 
     "relation": "Expert" 
 
     }, { 
 
     "target": 6, 
 
     "source": 5, 
 
     "relation": "Trainee" 
 
     }, { 
 
     "target": 7, 
 
     "source": 5, 
 
     "relation": "Technology;New Firm" 
 
     }, { 
 
     "target": 8, 
 
     "source": 4, 
 
     "relation": "Expert" 
 
     }, { 
 
     "target": 9, 
 
     "source": 4, 
 
     "relation": "New Firm" 
 
     }, { 
 
     "target": 8, 
 
     "source": 4, 
 
     "relation": "Expert" 
 
     }, { 
 
     "target": 9, 
 
     "source": 4, 
 
     "relation": "New Firm" 
 
     }, { 
 
     "target": 6, 
 
     "source": 5, 
 
     "relation": "Trainee" 
 
     }, { 
 
     "target": 7, 
 
     "source": 5, 
 
     "relation": "Technology;New Firm" 
 
     }] 
 
    }; 
 

 
    var svg = d3.select("svg"), 
 
     width = +svg.attr("width"), 
 
     height = +svg.attr("height"); 
 

 
    var graph = root; 
 

 
    var w = window, 
 
     d = document, 
 
     e = d.documentElement, 
 
     g = d.getElementsByTagName('body')[0], 
 
     x = w.innerWidth || e.clientWidth || g.clientWidth, 
 
     y = w.innerHeight || e.clientHeight || g.clientHeight; 
 

 
    var realWidth = width; 
 
    var width = x; 
 
    var height = y; 
 
    var img_w = 24; 
 
    var img_h = 24; 
 
    var k = Math.sqrt(root.nodes.length/(width * height)); 
 

 
    var simulation = d3.forceSimulation() 
 
     .force("link", d3.forceLink().id(function(d) { 
 
     return d.id; 
 
     }).distance(200)) 
 
     .force("charge", d3.forceManyBody().strength(-5/k)) 
 
     .force("center", d3.forceCenter(width/2, height/2)); 
 

 
    var link = svg.append("g") 
 
     .attr("class", "links") 
 
     .selectAll("line") 
 
     .data(graph.links) 
 
     .enter().append("line"); 
 

 
    var node = svg.append("g") 
 
     .attr("class", "nodes") 
 
     .selectAll("circle") 
 
     .data(graph.nodes) 
 
     .enter().append("image") 
 
     .attr("width", img_w) 
 
     .attr("height", img_h) 
 
     .attr("xlink:href", function(d) { 
 
     return d.image; 
 
     }) 
 
     .call(d3.drag() 
 
     .on("start", dragstarted) 
 
     .on("drag", dragged) 
 
     .on("end", dragended)); 
 

 
    var links_text = svg.selectAll(".linetext") 
 
     .data(graph.links) 
 
     .enter() 
 
     .append("text") 
 
     .attr("class", "linetext slds-text-heading--small") 
 
     .attr("text-anchor", "middle") 
 
     .text(function(d) { 
 
     return '[' + d.relation + ']'; 
 
     }); 
 

 
    var nodes_text = svg.selectAll(".nodetext") 
 
     .data(graph.nodes) 
 
     .enter() 
 
     .append("text") 
 
     .attr("class", "nodetext slds-text-heading--label") 
 
     .attr("text-anchor", "middle") 
 
     .attr("dx", -20) 
 
     .attr("dy", 20) 
 
     .text(function(d) { 
 
     return (d.subname != '' ? (d.subname + ': ') : '') + d.name; 
 
     }); 
 

 
    simulation 
 
     .nodes(graph.nodes) 
 
     .on("tick", ticked); 
 

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

 
    function ticked() { 
 
     link 
 
     .attr("x1", function(d) { 
 
      var xPos = d.source.x; 
 
      if (xPos < 0) return 0; 
 
      if (xPos > (960 - img_w)) return (960 - img_w); 
 
      return xPos; 
 
     }) 
 
     .attr("y1", function(d) { 
 
      var yPos = d.source.y; 
 
      if (yPos < 0) return 0; 
 
      if (yPos > (600 - img_h)) return (600 - img_h); 
 
      return yPos; 
 
     }) 
 
     .attr("x2", function(d) { 
 
      var xPos = d.target.x; 
 
      if (xPos < 0) return 0; 
 
      if (xPos > (960 - img_w)) return (960 - img_w); 
 
      return xPos; 
 
     }) 
 
     .attr("y2", function(d) { 
 
      var yPos = d.target.y; 
 
      if (yPos < 0) return 0; 
 
      if (yPos > (600 - img_h)) return (600 - img_h); 
 
      return yPos; 
 
     }); 
 

 
     links_text 
 
     .attr("x", function(d) { 
 
      var xPos = (d.source.x + d.target.x)/2; 
 
      if (xPos < 0) return 0; 
 
      if (xPos > (960 - img_w)) return (960 - img_w); 
 
      return xPos; 
 
     }) 
 
     .attr("y", function(d) { 
 
      var yPos = (d.source.y + d.target.y)/2; 
 
      if (yPos < 0) return 0; 
 
      if (yPos > (600 - img_h)) return (600 - img_h); 
 
      return yPos; 
 
     }); 
 

 

 
     node 
 
     .attr("x", function(d) { 
 
      var xPos = (d.x - img_w /2); 
 
      if (xPos < 0) return 0; 
 
      if (xPos > (960 - img_w)) return (960 - img_w); 
 
      return xPos; 
 
     }) 
 
     .attr("y", function(d) { 
 
      var yPos = d.y; 
 
      if (yPos < 0) return 0; 
 
      if (yPos > (600 - img_h)) return (600 - img_h); 
 
      return yPos; 
 
     }); 
 

 
     nodes_text 
 
     .attr("x", function(d) { 
 
      return d.x + 20 
 
     }) 
 
     .attr("y", function(d) { 
 
      return d.y + img_w/2; 
 
     }); 
 
    } 
 

 

 
    function dragstarted(d) { 
 
     if (!d3.event.active) simulation.alphaTarget(0.3).restart(); 
 
     d.fx = d.x; 
 
     d.fy = d.y; 
 
    } 
 

 
    function dragged(d) { 
 
     d.fx = d3.event.x; 
 
     d.fy = d3.event.y; 
 
    } 
 

 
    function dragended(d) { 
 
     if (!d3.event.active) simulation.alphaTarget(0); 
 
     d.fx = null; 
 
     d.fy = null; 
 
    } 
 
    </script> 
 
</body> 
 

 
</html>

+0

Dank @Mark, Sie waren immens hilfreich. Ich bin in der Lage, die Grafik mit den vorgeschlagenen Änderungen anständig aussehen zu lassen. Ich habe sogar einen Hintergrund White Rect zu den Labels hinzugefügt, so dass Labels, so dass Labels nicht mit Links zwischen ihnen überschrieben werden. Der letzte Ratschlag, den ich von Ihnen eingeholt habe, ist, können wir eine Funktion einführen, um zu erkennen, ob sich Etiketten (Knotentext/Linktext) überlappen? – VarunC

+0

Ich habe nicht versucht, Etiketten wie diese selbst zu implementieren, aber [dieser Block] (http://bl.ocks.org/MoritzStefaner/1377729) könnte das sein, was Sie wollen. – ropeladder