2012-06-19 6 views
39

Ich habe den Beispielcode von this d3 project verwendet, um zu lernen, wie man d3-Graphen anzeigt, und ich kann nicht scheinen, dass Text in der Mitte der Kreise angezeigt wird (ähnlich wie und this example). Ich habe an anderen Beispielen gesucht und haben versucht, das Hinzufügend3 Knotenbeschriftung

node.append("title").text("Node Name To Display") 

und

node.append("text") 
    .attr("text-anchor", "middle") 
    .attr("dy", ".3em").text("Node Name To Display") 

direkt nach dem Knoten definiert, aber die einzigen Ergebnisse, die ich sehe, ist „Knotennamen anzeigen“ zeigt, wenn ich schweben über jeden Knoten. Es wird nicht als Text im Kreis angezeigt. Muss ich mein eigenes SVG-Textobjekt schreiben und die Koordinaten bestimmen, auf denen es basierend auf den Koordinaten des Radius des Kreises platziert werden soll? Von den anderen beiden Beispielen scheint es, als ob d3 sich schon irgendwie darum kümmert. Ich kenne nur nicht das richtige Attribut zum Anrufen/Festlegen.

Antwort

76

Es gibt lots of examples zeigen, wie Etiketten hinzufügen grafisch darzustellen und Baum-Visualisierungen, aber ich würde wahrscheinlich mit dieser als einfachstes starten:

Sie haben nicht gepostet ein Link zu Ihrem Code, aber ich denke, dass node bezieht sich auf eine Auswahl von SVG-Kreis-Elementen. Sie können keine Textelemente zu Kreiselementen hinzufügen, da Kreiselemente nicht containers sind; Das Hinzufügen eines Textelements zu einem Kreis wird ignoriert.

Normalerweise verwenden Sie ein G-Element, um ein Kreiselement (oder ein Bildelement wie oben) und ein Textelement für jeden Knoten zu gruppieren. Die resultierende Struktur sieht wie folgt aus:

<g class="node" transform="translate(130,492)"> 
    <circle r="4.5"/> 
    <text dx="12" dy=".35em">Gavroche</text> 
</g> 

ein data-join Verwenden Sie die G-Elemente für jeden Knoten zu erstellen, und dann selection.append verwenden für jeden einen Kreis und ein Textelement hinzuzufügen. Etwas wie folgt aus:

var node = svg.selectAll(".node") 
    .data(nodes) 
    .enter().append("g") 
    .attr("class", "node") 
    .call(force.drag); 

node.append("circle") 
    .attr("r", 4.5); 

node.append("text") 
    .attr("dx", 12) 
    .attr("dy", ".35em") 
    .text(function(d) { return d.name }); 

Ein Nachteil dieses Ansatzes ist, dass Sie die Etiketten auf der Kreise gezogen werden möchten. Da SVG den Z-Index noch nicht unterstützt, werden Elemente in der Reihenfolge der Dokumente gezeichnet. so verursacht der obige Ansatz, dass ein Etikett über seinen Kreis gezogen wird, aber es kann unter anderen Kreisen gezogen werden. Sie können dieses Problem beheben, indem zwei Daten-Verknüpfungen und getrennte Gruppen für Kreise und Erstellen von Etiketten, etwa so:

<g class="nodes"> 
    <circle transform="translate(130,492)" r="4.5"/> 
    <circle transform="translate(110,249)" r="4.5"/> 
    … 
</g> 
<g class="labels"> 
    <text transform="translate(130,492)" dx="12" dy=".35em">Gavroche</text> 
    <text transform="translate(110,249)" dx="12" dy=".35em">Valjean</text> 
    … 
</g> 

und die entsprechenden JavaScript:

var circle = svg.append("g") 
    .attr("class", "nodes") 
    .selectAll("circle") 
    .data(nodes) 
    .enter().append("circle") 
    .attr("r", 4.5) 
    .call(force.drag); 

var text = svg.append("g") 
    .attr("class", "labels") 
    .selectAll("text") 
    .data(nodes) 
    .enter().append("text") 
    .attr("dx", 12) 
    .attr("dy", ".35em") 
    .text(function(d) { return d.name }); 

Diese Technik im Mobile Patent Suits Beispiel verwendet wird (mit einem zusätzlichen Textelement zum Erstellen eines weißen Schattens).

1

ich diesen Leitfaden als sehr nützlich bei dem Versuch, etwas ähnliches zu erreichen: dieser Code

https://www.dashingd3js.com/svg-text-element

Basierend auf obigen Link wird Kreis Etiketten generieren:

<!DOCTYPE html> 
<html> 
    <head> 
     <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
     <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> 
    </head> 
<body style="overflow: hidden;"> 
<div id="canvas" style="overflow: hidden;"></div> 

<script type="text/javascript"> 

    var graph = { 
     "nodes": [ 
      {name: "1", "group": 1, x: 100, y: 90, r: 10 , connected : "2"}, 
      {name: "2", "group": 1, x: 200, y: 50, r: 15, connected : "1"}, 
      {name: "3", "group": 2, x: 200, y: 130, r: 25, connected : "1"} 
     ] 
    } 

    $(document).ready(function() { 

     var width = 2000; 
     var height = 2000; 

     var svg = d3.select("#canvas").append("svg") 
       .attr("width", width) 
       .attr("height", height) 
       .append("g"); 

     var lines = svg.attr("class", "line") 
       .selectAll("line").data(graph.nodes) 
       .enter().append("line") 
       .style("stroke", "gray") // <<<<< Add a color 
       .attr("x1", function (d, i) { 
        return d.x 
       }) 
       .attr("y1", function (d) { 
        return d.y 
       }) 
       .attr("x2", function (d) { 
        return findAttribute(d.connected).x 
       }) 
       .attr("y2", function (d) { 
        return findAttribute(d.connected).y 
       }) 

     var circles = svg.selectAll("circle") 
       .data(graph.nodes) 
       .enter().append("circle") 
       .style("stroke", "gray") 
       .style("fill", "white") 
       .attr("r", function (d, i) { 
        return d.r 
       }) 
       .attr("cx", function (d, i) { 
        return d.x 
       }) 
       .attr("cy", function (d, i) { 
        return d.y 
       }); 

     var text = svg.selectAll("text") 
           .data(graph.nodes) 
           .enter() 
           .append("text"); 

     var textLabels = text 
      .attr("x", function(d) { return d.x; }) 
      .attr("y", function(d) { return d.y; }) 
      .text(function (d) { return d.name }) 
      .attr("font-family", "sans-serif") 
      .attr("font-size", "10px") 
      .attr("fill", "red"); 

    }); 

    function findAttribute(name) { 
     for (var i = 0, len = graph.nodes.length; i < len; i++) { 
      if (graph.nodes[i].name === name) 
       return graph.nodes[i]; // Return as soon as the object is found 
     } 
     return null; // The object was not found 
    } 


</script> 
</body> 
</html> 
+0

Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. – Whymarrh

+0

@Whymarrh Antwort aktualisiert –

2

Wenn Sie die wachsen wollen Wenn Sie Knoten für große Beschriftungen verwenden möchten, können Sie die Eigenschaft getBBox eines SVG-Textknotens verwenden, nachdem Sie sie gezeichnet haben. Hier sind, wie ich es getan hätte, um eine Liste der Knoten mit festen Koordinaten und zwei mögliche Formen:

nodes.forEach(function(v) { 
    var nd; 
    var cx = v.coord[0]; 
    var cy = v.coord[1]; 

    switch (v.shape) { 
    case "circle": 
     nd = svg.append("circle"); 
     break; 
    case "rectangle": 
     nd = svg.append("rect"); 
     break; 
    } 

    var w = 10; 
    var h = 10; 
    if (v.label != "") { 
    var lText = svg.append("text"); 

    lText.attr("x", cx) 
     .attr("y", cy + 5) 
     .attr("class", "labelText") 
     .text(v.label); 

    var bbox = lText.node().getBBox(); 
    w = Math.max(w,bbox.width); 
    h = Math.max(h,bbox.height); 
    } 

    var pad = 4; 

    switch (v.shape) { 
    case "circle": 
     nd.attr("cx", cx) 
     .attr("cy", cy) 
     .attr("r", Math.sqrt(w*w + h*h)/2 + pad); 
     break; 
    case "rectangle": 
     nd.attr("x", cx - w/2 - pad) 
     .attr("y", cy - h/2 - pad) 
     .attr("width", w + 2*pad) 
     .attr("height", h + 2*pad); 
     break; 
    } 

}); 

Beachten Sie, dass die Form hinzugefügt wird, wird der Text hinzugefügt, dann die Form positioniert ist, um den Text oben anzeigen lassen.