2017-03-02 2 views
1

Je n'arrive pas à comprendre comment ajouter des étiquettes de noeuds à mon réseau dirigé par la force D3. Ce code obtient les étiquettes à apparaître, mais ils ne bougeront pas avec le réseau.Ajout d'étiquettes de noeuds au réseau D3

Comment puis-je ajouter le texte au noeud lui-même? Quelqu'un a-t'il des suggestions?

Merci beaucoup.

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

Vous avez oublié de coller les deux parties les plus importantes de votre code: la simulation et la fonction de la tique. –

+0

@GerardoFurtado Désolé! Merci d'avoir fait remarquer cela. J'ai ajouté le reste du code. – billowingblackcloud

Répondre

0

S'il vous plaît voir ce lien: http://codepen.io/rafszul/pen/KeAaG/

il pourrait vous aider.

essayez de remplacer "circle" by "rect" dans JS, CSS section.

il faut aussi replacer cet extrait dans le code JS pour spécifier la largeur et la hauteur du rectangle:

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

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