D3.js Opacity过滤器部分工作

时间:2017-01-09 23:11:45

标签: javascript d3.js checkbox

我有一个稳定的d3.js图表​​,大部分都运行良好。有4种节点类型:

     Agent,Customer,Phone,ID_Card

有复选框可以处理节点和链接的不透明度。如果选中代理客户,则两个节点及其之间的所有可能链接都是不透明的。图表的其余部分有

 opacity(0)

此外,还有一个搜索功能,可让用户使用以下节点属性搜索图表

    d.id

输入ID匹配的节点将保持不透明状态,图表的其余部分将淡出几秒钟

以下是 HTML

          <label>
    <input type="checkbox" name="checkb" value="Agent"> type=Agent</label>
  <br />
  <label>
    <input type="checkbox" name="checkb" value="Customer"> type=Customer</label>
  <br />
  <label>
    <input type="checkbox" name="checkb" value="Phone"> type=Phone</label>
  <br />
  <label>
    <input type="checkbox" name="checkb" value="ID_Card"> type=ID_Card</label>
  <br />

 <input type="text" id="node" />
  <button id="search">
    Search_Node
  </button>
</div>

以下是 javascript 代码,可确保所有过滤器协同工作。

例如,如果选中客户电话,并且搜索功能应用于搜索客户或电话,剩下的两个未经检查的节点仍将保留在

   opacity(0)

搜索将仅应用于子图。

  d3.selectAll("input[name=checkb]").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("checkb");

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

    node.filter(function(d) {
        return checkedBoxes.indexOf(d.type) === -1;
      })
      .style("opacity", "0");

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

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


  });

  // get the checkboxes
  var typeAgentChk = document.querySelectorAll('input[value="Agent"]')[0];
  var typeCustomerChk = document.querySelectorAll('input[value="Customer"]')[0];
  var typePhoneChk = document.querySelectorAll('input[value="Phone"]')[0];
  var typeIDCardChk = document.querySelectorAll('input[value="ID_Card"]')[0];

  var checkBoxes = [typeAgentChk, typeCustomerChk, typePhoneChk, typeIDCardChk];
  var nodeTypes = ["Agent", "Customer", "Phone", "ID_Card"];


  var filterByCheckBox = function(el) {
    if (el.checked) {
      // filter
      filterBy("type", el.value, false);
    } else {
      removeFilterFor("type", el.value);
    }
  }

  var removeFilterFor = function(attribute, value) {
    var node = svg.selectAll(".node");
    var link = svg.selectAll(".link");
    var selected = node.filter(function(d) { // filter by attribute/value
        return d[attribute] == value;
      })
      .style("opacity", 0)
      .each(function(d) {
        var index = filtered.indexOf(d.id);
        if (index > -1) {
          filtered.splice(index, 1);
        }
      });
  }
  var filterBy = function(attribute, value, restoreAll, highlightSelected) {
    // get nodes and links - could be moved outside for efficiency
    var node = svg.selectAll(".node");
    var link = svg.selectAll(".link");
    if (value == "none" || value == null) { // do we need this?
      node.style("stroke", "white").style("stroke-width", "1");
    } else {
      var selected = node.filter(function(d) { // filter by attribute/value
        return d[attribute] == value;
      });

      // get any nodes we have filtered before
      var alreadyFiltered = node.filter(function(d) {
        return filtered.indexOf(d.id) > -1;
      })
      var alreadyFilteredLinks = link.filter(function(d) {
        return filtered.indexOf(d.source.id) > -1 && filtered.indexOf(d.target.id) > -1;
      })
      // hide all
      node.style("opacity", 0);
      link.style("opacity", 0);
      if (highlightSelected) {

        svg.selectAll(".node, .link").transition()
          .duration(1000)
          .style("opacity", 0);
      }
      selected.style("opacity", 1)
        .each(function(d) { // save the id's in the filtered list
          if (filtered.indexOf(d.id) == -1) {
            filtered.push(d.id);
          }
        });

      // but the already filtered and the currently selected
      alreadyFiltered.transition()
        .duration(3000)
        .style("opacity", 1);
      alreadyFilteredLinks.transition()
        .duration(3000)
        .style("opacity", 1);



      if (restoreAll) { // restore all 
        filtered = [];
        svg.selectAll(".node, .link").transition()
          .duration(5000)
          .style("opacity", 1);
      }
    }
  }



for (let i = 0; i < checkBoxes.length; i++) {
    checkBoxes[i].checked = true;
    //filterByCheckBox(checkBoxes[i]); // add all ids in filtered
    checkBoxes[i].addEventListener("click", function() {
      filterByCheckBox(checkBoxes[i])
    });
  }

  searchBtn.addEventListener("click", function() {
    // get value to filter with
    var selectedVal = document.getElementById('node').value;
    if (nodeTypes.indexOf(selectedVal) > -1) { // we filter by type
      filterBy("type", selectedVal, false);
    } else {
      console.log("filterBy", "id", selectedVal)
      filterBy("id", selectedVal, false, true);
    }
  });

这似乎在很大程度上与预期一致。复选框的取消选中工作正常,似乎可以在

处创建未经检查的节点
 opacity(0)

但是当再次检查那些节点时,它似乎效果不佳。

例如,如果客户手机仍未检查,其他两项仍未选中,则只有客户手机是可见的。但是,如果再次重新检查代理节点,即使 ID_Card 节点仍然未选中,也会显示该节点。

在任何节点的检查期间都是如此。即使未经检查的节点也会显示。

以下是fiddle

0 个答案:

没有答案