Jugal Patel Jugal Patel - 4 years ago 815
Javascript Question

d3 force only display certain links and nodes on click

I've got a force directed layout set up in d3, but I'm trying to make it so that only certain links and nodes display, in accordance with a horizontal group of buttons I have set up.

Essentially, the force layout would display links and nodes based on whatever buttons are toggled on. For example, if I click on academia, federal, and commonwealth, only the links and nodes under those groups would display in my visualization. Does anyone know how I can set this up?

Here is a link to my code: https://plnkr.co/edit/QZ8chcsOj64oYJnIqz1J?p=preview

Here are my buttons (lines 27-64 in index.html):

<div class="legend;" style="margin-top: 0px; margin-bottom: 15px;">

<div class="ngolegend item">
<svg height="20" width="300">
<circle cx="15" cy="12" r="4" stroke="black" stroke-width="1" fill="orange" fill-opacity="0.6" />
<text x="25" y="16" font-family="serif" font-size="12px">Non-Governmental Organizations</text>
</svg>
</div>

<div class="academialegend item">
<svg height="20" width="300">
<circle cx="15" cy="12" r="4" stroke="black" stroke-width="1" fill="steelblue" fill-opacity="0.6" />
<text x="25" y="16" font-family="serif" font-size="12px">Academia</text>
</svg>
</div>

<div class="commonwealthlegend item">
<svg height="20" width="300">
<circle cx="15" cy="12" r="4" stroke="black" stroke-width="1" fill="green" fill-opacity="0.6" />
<text x="25" y="16" font-family="serif" font-size="12px">Commonwealth</text>
</svg>
</div>

<div class="federallegend item">
<svg height="20" width="300">
<circle cx="15" cy="12" r="4" stroke="black" stroke-width="1" fill="red" fill-opacity="0.6" />
<text x="25" y="16" font-family="serif" font-size="12px">Federal</text>
</svg>
</div>

<div class="militarylegend item">
<svg height="20" width="300">
<circle cx="15" cy="12" r="4" stroke="black" stroke-width="1" fill="purple" fill-opacity="0.6" />
<text x="25" y="16" font-family="serif" font-size="12px">Military</text>
</svg>
</div>

</div>


And I'm guessing the code I would need would go in here? (lines 207-209 in script.js):

$(".item").click(function () {
$(this).toggleClass("gray");


});

Answer Source

You can add extra information on these nodes and links by using data-[name] to distinguish different types of data, such as data-type.

 var node = svg.selectAll(".node")
        .data(json.nodes)
        .enter().append("g")
        .attr("data-type", function(d){
          return d.Sector; // add data attributes for later usage.
        })
        .attr("class","node") // better to give them class name

Then add filtering code like this in the dashboard toggle function:

$(".item").click(function () {
  $(this).toggleClass("gray");
  var text = $(this).find("text").text()
  if($(this).hasClass("gray")){
     d3.selectAll(".node")
       .filter(function(d,i){
         return d3.select(this).attr("data-type") == text;
       })
       // filter nodes with the same type, and make it invisible
      .style("opacity",0)
 }else {
    d3.selectAll(".node")
     .filter(function(d,i){
     return d3.select(this).attr("data-type") == text;
    })
   .style("opacity",1)
 }
});

The method is similar for links, I suppose you can add the type info into the data source. And keep the name of the 'type' consistent while filtering('Commonwealth' V.S 'Commonwealth of Virginia'). Example plunkr here, click on 'Academia', 'Federal', 'Military' to see how it works for node (the other two types aren't working because of the naming consistency issue).

Update for question in comments: To achieve the effect of only show information tab while clicking on children nodes, you can check the name of the parent node and compare it with the dashboard items:

 // collect the items in the dashboard panel
 var items = []; 
 $(".item").each(function(){
   items.push($(this).find("text").text())
 })

Then in the click event listener:

if($.inArray(d.name, items) !== -1){return}  
// check if this node is the parent node describe in dashboard panel

Example plunkr here. Again, there is some data inconsistency just for the 'common wealth' type, should be 'common wealth of virgina'. (click on 'federal', 'academia', 'non-government organization' types to see how it turns out)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download