Search code examples
javascriptjqueryd3.jsradio-buttongraph-visualization

d3.js Changing the opacity of nodes and it's outgoing and incoming links based on a filter


I have a fully working force directed graph.

I am trying to add radio buttons and clicking on them should dynamically change the opacity of nodes , based on a condition.

HTML

    <style>
  .links line {
    stroke: #999;
    stroke-opacity: 0.6;
  }

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

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

  div.tooltip {
    position: absolute;
    background-color: white;
    max-width: 200px;
    height: auto;
    padding: 1px;
    border-style: solid;
    border-radius: 4px;
    border-width: 1px;
    box-shadow: 3px 3px 10px rgba(0, 0, 0, .5);
    pointer-events: none;
  }

</style>
<svg id="Network_graph" width="400" height="350"></svg>
<div id="map"></div>
<div id="legend">
  <h3>Filter</h3>
  <div class="input-group" id="filters">
    <label>
      <input type="radio" name="filter" value="All" checked="checked"> All</label>
    <br />
    <label>
      <label>
        <input type="radio" name="filter" value="Agent"> Agent</label>
      <br />
      <label>
        <input type="radio" name="filter" value="Customer"> Customer</label>
      <br />
      <label>
        <input type="radio" name="filter" value="Phone"> Phone</label>
      <br />
      <label>
        <input type="radio" name="filter" value="ID_Card"> ID_Card </label>

  </div>
</div>





</button>

My JSON data is of the below format:

JSON

var IDData = JSON.stringify([
  ["node/105173", "node/38180995", "Agent", "Customer", "1379644.0", 1, 264, "1374903"],
  ["node/1061", "node/21373542", "Agent", "Customer", "530848.0", 1, 3000, "529502"],
  ["node/10750", "node/59648369", "Agent", "Customer", "1454228.0", 1, 120, "1454118"],
  ["node/10750", "node/78569210", "Agent", "Customer", "1425251.0", 1, 234, "1421416"],
  ["node/10750", "node/96726118", "Agent", "Customer", "1376239.0", 1, 434, "1376152"],
  ["node/10946829", "node/11190", "Customer", "Agent", "1409620.0", 20, 3380, "1406665"],
  ["node/10946829", "node/57774036", "Customer", "Customer", "1460029.0", 3, 960, "1459731"],
  ["node/109947", "node/97911872", "Agent", "Customer", "1323025.0", 1, 600, "1315582"],..])

Using this function , I convert this JSON data in a suitable format to render the graphs,

$(document).ready(function() {

    console.log(IDData);
    var galData = JSON.parse(IDData);
    var startnodes = [];
    var endnodes = [];
    var startnodetype = [];
    var endnodetype = [];
    var PayTime = [];
    var TXN_COUNT = [];
    var Total_Amt = [];
    var SendTime = [];
    galData.map(function(e, i) {
        startnodes.push(e[0]);
        endnodes.push(e[1]);
        startnodetype.push(e[2]);
        endnodetype.push(e[3]);
        PayTime.push(e[4]);
        TXN_COUNT.push(e[5]);
        Total_Amt.push(e[6]);
        SendTime.push(e[7]);
    });
    var final_data = createNodes(startnodes, endnodes, startnodetype, endnodetype, depth, PayTime, TXN_COUNT, Total_Amt, SendTime);
    makeGraph("#Network_graph", final_data);

});

Working JsFiddle is here.It is inspired from this example of d3.js library.

So , my graph has 4 types of Nodes ; Agent,Customer,Phone,ID_Card. These are represented by

  d.type

So , now I have written this below piece of code; that should filter the graph based on the radio button being selected, So , for instance selection on radio button with value "Agent" should reduce the opacity of other nodes and links , except those links that are outgoing and incoming from all "Agent" nodes.

d3.selectAll("input[name=filter]").on("change", function(d){


      var value = this.value;

      node.style("opacity", 1);
      link.style("opacity", 1);


      if (value !== "all"){
        value = +this.value;
        node.filter(function(d){
          return d.type != value;
        })
        .style("opacity", "0.5");

        link.filter(function(d){
          return d.source.type != value ||
                 d.target.type != value;
        })
        .style("opacity", "0.5");
      }



    });

Seems like there is something missing still and running this is not changing the opacity. I am very new to javascrpt and d3.js and lack expertise. So , looking for some help.


Solution

  • You have two problems here.

    Problem 1: Scope

    Inside your "change" function, you're making reference to node and link. But both node and link exist only inside makeGraph function.

    The solution is moving all that event handler to inside makeGraph function.

    Problem 2: Type conversion

    When you do this:

    value = +this.value;
    

    You're trying to convert a string which has no numbers to a number. So:

    console.log(+this.value);//returns NaN
    

    And you're not doing anything with NaN.

    Solution: keep the strings.

    Here is your updated fiddle: https://jsfiddle.net/u9y4m32k/