2017-03-02 18 views
1

D3 강제 지정 네트워크에 노드 레이블을 추가하는 방법을 알 수 없습니다. 이 코드는 표시 할 레이블을 가져 오지만 네트워크와 함께 이동하지는 않습니다.D3 네트워크에 노드 레이블 추가

어떻게 노드 자체에 텍스트를 추가 할 수 있습니까? 누구 제안이 있습니까?

감사합니다.

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 
.links line { 
    stroke: #999; 
    stroke-opacity: .6; 
    shape-rendering: geometricPrecision; 
} 

.nodes circle { 
    stroke: #fff; 
    stroke-width: 1.5px; 
} 

.node text { 
    pointer-events: none; 
    font: 10px sans-serif; 
} 

#tools div { 
    display: inline; 
} 

form, 
select { 
    float: right; 
    display: inline; 
} 
</style> 

<body> 
<div id='tools'></div> 
<svg width="960" height="600"></svg> 
<script src="https://d3js.org/d3.v4.min.js"></script> 
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> 
<script> 
    var svg = d3.select("svg"), 
     width = +svg.attr("width"), 
     height = +svg.attr("height"); 

    var graph; //Global variable for the graph 

    svg.append('rect') 
     .attr('width', '100%') 
     .attr('height', '100%') 
     .attr('fill', '#FFFFFF'); 

    // Call zoom for svg container. 
    svg.call(d3.zoom().on('zoom', zoomed)).on("dblclick.zoom", null); 
    var container = svg.append('g'); 
    //Create scales for color and edge weight 

    var color = d3.scaleLinear() 
     .domain([1776, 2017]) 
     .range([0.1, 1]); 

    var weight = d3.scaleLinear() 
     .domain([0, 1]) 
     .range([1, 5]); 

    // Create form for search (see function below). 
    var search = d3.select("div#tools").append('form').attr('onsubmit', 'return false;'); 
    var box = search.append('input') 
     .attr('type', 'text') 
     .attr('id', 'searchTerm') 
     .attr('placeholder', 'Type to search...'); 
    var button = search.append('input') 
     .attr('type', 'button') 
     .attr('value', 'Search') 
     .on('click', function() { 
      searchNodes(); 
     }); 

    //Toggle for ego networks on click (function below). 
    var toggle = 0; 

    //Create groups for nodes and links 
    var link = container.append("g") 
     .attr("class", "links") 
     .selectAll(".link"), 
     node = container.append("g") 
     .attr("class", "nodes") 
     .selectAll(".node"); 


    //Get data from json file, assign that data to graph variable. 
    d3.json("semantic_great_nouns.json", function(error, json) { 
     if (error) throw error; 
     graph = json; 
     update(); 
    }); 

    // Zooming function translates the size of the svg container. 
    function zoomed() { 
     container.attr("transform", "translate(" + d3.event.transform.x + ", " + d3.event.transform.y + ") scale(" + d3.event.transform.k + ")"); 
    } 
    // Search for nodes by making all unmatched nodes temporarily transparent. 
    function searchNodes() { 
     var term = document.getElementById('searchTerm').value; 
     var selected = container.selectAll('.node').filter(function(d, i) { 
      return d.id.toString().search(term.toLowerCase()) == -1; 
     }); 
     selected.style('opacity', '0'); 
     var link = container.selectAll('.link'); 
     link.style('stroke-opacity', '0'); 
     d3.selectAll('.node').transition() 
      .duration(20000) 
      .style('opacity', '1'); 
     d3.selectAll('.link').transition().duration(20000).style('stroke-opacity', '1'); 
    } 
    //Draw the graph! 
    function update() { 
     //Parameters for force layout simulation 
     var simulation = d3.forceSimulation(graph.nodes) 
      .force("link", d3.forceLink(graph.links)) //.id(function(d) { return d.id; })) 
      .force("charge", d3.forceManyBody().strength([-300])) //.distanceMax([500])) 
      .force("center", d3.forceCenter(width/2, height/2)) 
      .force("x", d3.forceX()) 
      .force("y", d3.forceY()) 
      .stop(); 
     //The graph will be drawn behind the scenes and then displayed in static form. 
     //This code tells the program how many times to iterate through the layout simulation. 
     for (var i = 0, n = Math.ceil(Math.log(simulation.alphaMin())/Math.log(1 - simulation.alphaDecay())); i < n; ++i) { 
      simulation.tick(); 
     } 
     // Data join with links and corresponding nodes. 
     //If we wanted to reload the graph with an adjusted node set, we could do so. 
     link = link.data(graph.links, function(d) { 
      return d.source.id + ', ' + d.target.id; 
     }); 
     link.exit().remove(); 
     var linkEnter = link.enter().append('line') 
      .attr('class', 'link'); 
     link = linkEnter.merge(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; 
      }) 
      .attr("stroke-width", function(d) { 
       return weight(d.weight); 
      }); 

     // When adding and removing graph.nodes, reassert attributes and behaviors. 
     node = node.data(graph.nodes, function(d) { 
      return d.id; 
     }); 
     node.exit().remove(); 
     var nodeEnter = node.enter().append('circle') 
      .attr('r', 20) 
      .attr("fill", function(d) { 
       if (d.bipartite == 1) { 
        return '#103def'; 
       } else { 
        return '#ed1d0e'; 
       } 
      }) 
      //color bipartite nodes 
      .attr('class', 'node') 
      .attr('id', function(d) { 
       return "n" + d.id.toString(); 
      }) 
      .attr('clickToggle', 0) 
      .attr("cx", function(d) { 
       return d.x; 
      }) 
      .attr("cy", function(d) { 
       return d.y; 
      }) 
      // On click, toggle ego networks for the selected node. (See function below.) 
      .on('click', function(d) { 
       toggleClick(d); 
      }); 
     node = nodeEnter.merge(node); 

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

     var label = svg.append("g").attr("class", "labels").selectAll("g") 
      .data(graph.nodes) 
      .enter().append("g"); 

     label.append("text") 
      .attr("x", 14) 
      .attr("y", ".31em") 
      .style("font-family", "sans-serif") 
      .style("font-size", "0.7em") 
      .text(function(d) { 
       return d.id; 
      }) 
      .attr("x", function(d) { 
       return d.x; 
      }) 
      .attr("y", function(d) { 
       return d.y; 
      }); 

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

     // simulation.on("tick", function() { 
     // 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;});""" 

     //node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 
     // }); 
     //d3.selectAll("circle").attr("cx", function (d) {return d.x;}) 
     // .attr("cy", function (d) {return d.y;}); 
     //d3.selectAll("text").attr("x", function (d) {return d.x;}) 
     // .attr("y", function (d) {return d.y;}); 
     //}); 
     //node.append("title") 
     //.text(function(d) { return d.id; }); 
    } 


    // A function to handle click toggling based on neighboring nodes. 
    function toggleClick(d) { 
     // Make object of all neighboring nodes. 
     connectedNodes = {}; 
     connectedNodes[d.id] = true; 
     graph.links.forEach(function(l) { 
      if (l.source.id == d.id) { 
       connectedNodes[l.target.id] = true; 
      } else if (l.target.id == d.id) { 
       connectedNodes[l.source.id] = true; 
      }; 
     }); 
     if (toggle == 0) { 
      // Ternary operator restyles links and nodes if they are adjacent. 
      d3.selectAll('.link').style('stroke-opacity', function(l) { 
       return l.target == d || l.source == d ? 1 : 0.2; 
      }); 
      d3.selectAll('.node').style('opacity', function(n) { 
       if (n.id in connectedNodes) { 
        return 1; 
       } else { 
        return 0.2; 
       }; 
      }); 
      // Show information when node is clicked 
      d3.select('div#tools').append('span').text(d.date); 
      toggle = 1; 
     } else { 
      // Restore nodes and links to normal opacity. 
      d3.selectAll('.link').style('stroke-opacity', 0.6); 
      d3.selectAll('.node').style('opacity', 1); 
      d3.selectAll('span').remove(); 
      toggle = 0; 
     } 
    } 
</script> 

+0

당신은 코드의 두 가지 중요한 부분을 붙여 잊었 :

는 사각형의 너비와 높이를 지정하는 JS 코드로이 코드로 교체 시뮬레이션 및 틱 기능을. –

+0

@GerardoFurtado 죄송합니다! 그 점을 지적 해 주셔서 감사합니다. 나는 나머지 코드를 추가했다. – billowingblackcloud

답변

0

이 링크를 참조하십시오 http://codepen.io/rafszul/pen/KeAaG/

당신을 도움이 될 수 있습니다.

"circle" by "rect"JS, CSS 섹션으로 바꾸어보세요.

var circle = svg.append("g").selectAll("rect") 

    .data(force.nodes()) 
    .enter().append("rect") 
    .attr("width", 15) 
    .attr("height", 15) 
    .call(force.drag);