Home > Software engineering >  Filter nodes and links whitout changing the opacity d3js
Filter nodes and links whitout changing the opacity d3js

Time:10-11

Can anyone help me try to filter this data (nodes and links) by checkbox type without touching the opacity but doing an update each time on nodes and links s' please I have tried several ways but can't change anything? In this code I managed to filter them by changing the opacity but what I want is to remove them and add them each time without changing the color of the nodes and links.

Here's my HTML/CSS/JS file:

<style>

.link {
  stroke: #ccc;
  stroke-width: 1.5px;
  fill:transparent;
}
  
</style>
<body>
      <div>
          <input type="checkbox" value="Application Server" id="applicationServer" name="check" checked>
          <label for="applicationServer">Application Server</label>
      </div>
      <div>
          <input type="checkbox" value="Access Switch" id="acessSwitch" name="check" checked>
          <label for="acessSwitch">Access Switch</label>
      </div>
      <div>
          <input type="checkbox" value="Distribution Switch" id="distSwitch" name="check" checked>
          <label for="distSwitch">Distribution Switch</label>
      </div>

<script src="//d3js.org/d3.v3.min.js"></script>
<script>

var width = 1060,
    height = 500

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);
 
var color = d3.scale.category20();

var force = d3.layout.force()
    .gravity(0.05)
    .distance(60)
    .charge(-100)
    .size([width, height]);

d3.json("data2.json", function(error, json) {
  if (error) throw error;

  force
      .nodes(json.nodes)
      .links(json.links)
      .start();

  var link = svg.selectAll(".link")
      .data(json.links)
    .enter().append("line")
      .attr("class", "link");

  var node = svg.selectAll(".node")
      .data(json.nodes)
    .enter().append("g")
      .attr("class", "node")
      .call(force.drag);


  var circles = node.append("circle")
    .attr("r", 8)
    .attr("fill", function(d) { return color(d.group); });

      d3.selectAll("input[name=check]").on("change", function() {
  function getCheckedBoxes(chkboxName) {
          var checkboxes = document.getElementsByName(chkboxName);
          var checkboxesChecked = [];
          for (var i=0; i<checkboxes.length; i  ) {
             if (checkboxes[i].checked) {
                checkboxesChecked.push(checkboxes[i].defaultValue);
             }
          }
          return checkboxesChecked.length > 0 ? checkboxesChecked : " ";
        }

        var checkedBoxes = getCheckedBoxes("check");
    
    node.style("opacity", 1);
    link.style("opacity", 1);
    
      node.filter(function(d) {
          return checkedBoxes.indexOf(d.role) === -1;
        })
        .style("opacity", "0");

    link.filter(function(d) {
          return checkedBoxes.indexOf(d.source.type) === -1 && 
          checkedBoxes.indexOf(d.target.type) === -1;
        })
        .style("opacity", "0.2");

      link.filter(function(d) {
          return checkedBoxes.indexOf(d.source.type) > -1 && 
          checkedBoxes.indexOf(d.target.type) > -1;
        })
        .style("opacity", "0.2");
  
  
  });

  force.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   ")"; });
  });
});

</script>

Here's the json file "data2.json":

 {"nodes": [
        {"id": 1, "name": "Beric", "role": "Application Server", "group": 2}, 
        {"id": 2, "name": "dmi01-stamford-sw01", "role": "Access Switch", "group": 5}, 
        {"id": 4, "name": "ncsu118-distswitch1", "role": "Distribution Switch", "group": 6}, 
        {"id": 8, "name": "ncsu128-distswitch1", "role": "Distribution Switch", "group": 6}
    ],
         "links": [
             {"source": 1, "target": 2}, 
            {"source": 4, "target": 8}, {"source": 4, "target": 2}
            ]}

Please help !!!

CodePudding user response:

Every time a checkbox is updated, you can compute a boolean value for each node to determine if it should be active or not based on its role and the active checkboxes:

document.getElementsByName("check").forEach(checkbox => {
    data.nodes.filter(n => n.role === checkbox.value).forEach(n => n.active = checkbox.checked);
});

Then you filter the nodes and links based on this active attribute:

var activeNodes = data.nodes.filter(n => n.active);
var activeLinks = data.links.filter(l => activeNodes.includes(l.source) && activeNodes.includes(l.target));

Then you update the graph using d3 and the general update pattern.

You can find a working example here: https://codepen.io/ccasenove/pen/YzLJEmK

  • Related