2012-06-19 37 views
39

Tôi đã sử dụng mã mẫu từ this d3 project để tìm hiểu cách hiển thị biểu đồ d3 và tôi dường như không thể hiển thị văn bản ở giữa các vòng kết nối (tương tự như this examplethis example). Tôi đã nhìn vào ví dụ khác và đã thử thêmd3 Node Labeling

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

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

ngay sau khi nút được xác định nhưng kết quả duy nhất tôi thấy là "Node Name để hiển thị" được hiển thị khi tôi di chuột trên mỗi nút. Nó không hiển thị dưới dạng văn bản bên trong vòng tròn. Tôi có phải viết đối tượng văn bản svg của riêng mình và xác định tọa độ của nó mà nó cần phải được đặt tại dựa trên tọa độ bán kính của vòng tròn không? Từ hai ví dụ khác, có vẻ như d3 đã quan tâm đến điều này bằng cách nào đó. Tôi chỉ không biết thuộc tính đúng để gọi/thiết lập.

Trả lời

76

lots of examples cho thấy làm thế nào để thêm nhãn để vẽ đồ thị và visualizations cây, nhưng tôi có thể bắt đầu với một này là đơn giản nhất:

Bạn chưa đăng tải một liên kết với mã của bạn, nhưng tôi đoán rằng node đề cập đến việc lựa chọn các phần tử vòng tròn SVG. Bạn không thể thêm yếu tố văn bản vào các yếu tố hình tròn vì các phần tử hình tròn không phải là containers; việc thêm phần tử văn bản vào vòng kết nối sẽ bị bỏ qua.

Thông thường bạn sử dụng phần tử G để nhóm phần tử vòng tròn (hoặc phần tử hình ảnh như trên) và phần tử văn bản cho mỗi nút. Cấu trúc kết quả trông như thế này:

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

Sử dụng một data-join để tạo ra các yếu tố G cho mỗi nút, và sau đó sử dụng selection.append để thêm một vòng tròn và một yếu tố văn bản cho mỗi. Một cái gì đó như thế này:

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

Một nhược điểm của phương pháp này là bạn có thể muốn nhãn được vẽ trên đầu vòng tròn. Vì SVG chưa hỗ trợ chỉ mục z, các phần tử được vẽ theo thứ tự tài liệu; do đó, cách tiếp cận trên gây ra nhãn được vẽ phía trên vòng tròn nhưng có thể được vẽ trong các vòng kết nối khác. Bạn có thể khắc phục điều này bằng cách sử dụng hai dữ liệu tham gia và tạo các nhóm riêng biệt cho vòng tròn và nhãn, như vậy:

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

Và JavaScript tương ứng:

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

Kỹ thuật này được sử dụng trong ví dụ Mobile Patent Suits (với một yếu tố văn bản bổ sung được sử dụng để tạo ra một bóng trắng).

1

tôi thấy hướng dẫn này rất hữu ích trong việc cố gắng để đạt được một cái gì đó tương tự:

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

Dựa vào liên kết ở trên mã này sẽ tạo ra nhãn tròn:

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

Trong khi liên kết này có thể trả lời câu hỏi, tốt hơn nên bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo. Câu trả lời chỉ liên kết có thể trở thành không hợp lệ nếu trang được liên kết thay đổi. – Whymarrh

+0

@Whymarrh câu trả lời được cập nhật –

2

Nếu bạn muốn phát triển các các nút để phù hợp với các nhãn lớn, bạn có thể sử dụng thuộc tính getBBox của nút văn bản SVG sau khi bạn đã vẽ nó. Đây là cách tôi đã làm nó, đối với một danh sách các nút với tọa độ cố định, và hai hình thể:

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

}); 

Lưu ý rằng hình dạng được bổ sung, văn bản được thêm vào, sau đó hình là vị trí, để hiển thị văn bản ở trên cùng.