2012-06-19 26 views
39

He estado usando el código de ejemplo de this d3 project para aprender a mostrar gráficos d3 y parece que el texto no aparece en el medio de los círculos (similar a this example y this example). He mirado en otros ejemplos y he intentado añadird3 Etiquetado de nodo

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

y

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

justo después nodo está definido, pero los únicos resultados que veo es "Nombre de nodo para mostrar" está apareciendo cuando se ciernen sobre cada nodo. No aparece como texto dentro del círculo. ¿Tengo que escribir mi propio objeto de texto svg y determinar las coordenadas de las que necesita colocar en función de las coordenadas de radio del círculo? De los otros dos ejemplos, parece que d3 ya se preocupa por esto de alguna manera. Simplemente no sé el atributo correcto para llamar/establecer.

Respuesta

76

Hay lots of examples mostrando cómo añadir etiquetas a representar y visualizaciones de los árboles, pero probablemente me empezar con éste como el más simple:

No ha publicado un enlace a su código, pero supongo que node se refiere a una selección de elementos del círculo SVG. No puede agregar elementos de texto a los elementos del círculo porque los elementos del círculo no son containers; agregar un elemento de texto a un círculo será ignorado.

Normalmente, utiliza un elemento G para agrupar un elemento circular (o un elemento de imagen, como se indica anteriormente) y un elemento de texto para cada nodo. La estructura resultante tiene este aspecto:

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

Utilice un data-join para crear los elementos de G para cada nodo, y luego usar selection.append añadir un círculo y un elemento de texto para cada uno. Algo como esto:

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

Una desventaja de este enfoque es que es posible que desee que las etiquetas se dibujan encima de los círculos. Como SVG aún no es compatible con el índice z, los elementos se dibujan en orden de documento; por lo tanto, el enfoque anterior hace que se dibuje una etiqueta sobre su círculo, pero puede dibujarse bajo otros círculos. Puede solucionar este problema mediante el uso de dos datos se une y la creación de grupos separados para los círculos y etiquetas, así:

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

Y el JavaScript correspondiente:

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

Esta técnica se utiliza en el ejemplo Mobile Patent Suits (con un elemento de texto adicional usado para crear una sombra blanca).

1

encontré esta guía muy útil para tratar de lograr algo similar:

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

Basado en el enlace por encima de este código generará etiquetas círculo:

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

Si bien este enlace puede responder a la pregunta, es mejor incluir las partes esenciales de la respuesta aquí y proporcionar el enlace de referencia. Las respuestas de solo enlace pueden dejar de ser válidas si la página vinculada cambia. – Whymarrh

+0

@Whymarrh respuesta actualizada –

2

Si usted quiere hacer crecer la nodos para que quepan en etiquetas grandes, puede usar la propiedad getBox de un nodo de texto SVG después de haberlo dibujado. Así es como yo lo hice, para obtener una lista de nodos con coordenadas fijas y dos formas posibles:

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

}); 

Tenga en cuenta que se agrega a la forma, se añade el texto, continuación la forma se coloca, con el fin de obtener el texto para mostrar en la parte superior.