2012-06-19 10 views
39

Ho utilizzato il codice di esempio da this d3 project per imparare a visualizzare i grafici d3 e non riesco a visualizzare il testo nel mezzo dei cerchi (simile a this example e this example). Ho guardato in altri esempi e provato ad aggiungered3 Node Labelling

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

e

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

subito dopo il nodo è definito, ma gli unici risultati che vedo è "Nome nodo per visualizzare" sta rivelando quando mi passa il mouse su ciascun nodo. Non viene visualizzato come testo all'interno del cerchio. Devo scrivere il mio oggetto di testo svg e determinare le coordinate di ciò che deve essere posizionato in base alle coordinate del raggio del cerchio? Dagli altri due esempi, sembrerebbe che d3 già prenda cura di questo in qualche modo. Semplicemente non conosco l'attributo giusto per chiamare/impostare.

risposta

76

ci sono lots of examples che mostra come aggiungere le etichette da rappresentare graficamente e visualizzazioni degli alberi, ma probabilmente sarei Iniziamo con questo come il più semplice:

Non hai inviato un link al tuo codice, ma suppongo che lo node si riferisca ad una selezione di elementi del cerchio SVG. Non è possibile aggiungere elementi di testo agli elementi del cerchio perché gli elementi del cerchio non sono containers; l'aggiunta di un elemento testuale a un cerchio verrà ignorata.

Tipicamente si utilizza un elemento di G per raggruppare un elemento di cerchio (o un elemento di immagine, come sopra) e un elemento di testo per ciascun nodo. La struttura risultante è simile al seguente:

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

Utilizzare un data-join per creare gli elementi G per ogni nodo, e quindi utilizzare selection.append per aggiungere un cerchio e un elemento di testo per ciascuno. Qualcosa di simile a questo:

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 }); 

Un difetto di questo approccio è che si può decidere le etichette da trarre in cima dei cerchi. Dato che SVG non supporta ancora z-index, gli elementi vengono disegnati nell'ordine del documento; così, l'approccio di cui sopra provoca un'etichetta da trarre sopra del suo cerchio, ma può essere disegnato sotto altri cerchi. È possibile risolvere questo problema utilizzando due dati-join e la creazione di gruppi separati per i cerchi e le etichette, in questo modo:

<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> 

e il corrispondente 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 }); 

Questa tecnica viene utilizzata nell'esempio Mobile Patent Suits (con un elemento di testo aggiuntivo utilizzato per creare un'ombra bianca).

1

ho trovato questa guida molto utile nel cercare di realizzare qualcosa di simile:

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

In base a link qui sopra questo codice genererà etichette cerchio:

<!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

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il collegamento per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. – Whymarrh

+0

@Whymarrh risposta aggiornata –

2

Se si vuole far crescere il i nodi per adattarsi alle etichette di grandi dimensioni, è possibile utilizzare la proprietà getBBox di un nodo di testo SVG dopo averlo disegnato. Ecco come ho fatto, per una lista di nodi con coordinate fisse, e due forme possibili:

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; 
    } 

}); 

Nota che si aggiunge la forma, è aggiunto il testo, quindi la forma è posizionato, al fine di ottenere il testo da mostrare in alto.