突出显示节点及其邻居不与另一个不透明度过滤器同步

时间:2017-02-23 00:41:30

标签: javascript d3.js

我有一个功能齐全的d3.js力导向图。图表中有各种过滤器。

我现在正尝试使用突出显示功能,即如果双击该节点,则该节点及其所有邻居与图的其余部分相比具有更高的不透明度。再次双击任何节点,整个图形将变为可见。

这很好用:

 var toggle = 0;
//Create an array logging what is connected to what
var linkedByIndex = {};
for (i = 0; i < d3GraphData.nodes.length; i++) {
    linkedByIndex[i + "," + i] = 1;
};
d3GraphData.links.forEach(function (d) {
    linkedByIndex[d.source.index + "," + d.target.index] = 1;
});
//This function looks up whether a pair are neighbours
function neighboring(a, b) {
    return linkedByIndex[a.index + "," + b.index];
}
function connectedNodes() {
    if (toggle == 0) {
        //Reduce the opacity of all but the neighbouring nodes
        d = d3.select(this).node().__data__;

        node.style("opacity", function (o) {
            return neighboring(d, o) | neighboring(o, d) ? 1 : 0.1;
        });
        link.style("opacity", function (o) {
            return d.index==o.source.index | d.index==o.target.index ? 1 : 0.1;
        });
        //Reduce the op
        toggle = 1;
    } else {
        //Put them back to opacity=1
        node.style("opacity", 1);
        link.style("opacity", 1);
        toggle = 0;
    }
}

现在,我还通过复选框控制了另一个不透明度过滤器。取消选中复选框会使未选中的节点不可见。

有4种节点类型:

 Agent,Customer,Phone,ID_Card

节点具有属性

   d.visible:true

可见属性的当前状态取决于选中/取消选中的框,保持在不透明度过滤器的代码中。

下面是复选框部分的代码:

var circles = svg.selectAll(".node");
var lines = svg.selectAll(".link");

lines.style("opacity", function(d) {
  return getOpacity(d.source) && getOpacity(d.target) ? 1 : 0;
})
var nodeTypes = ["Agent", "Customer", "Phone", "ID_Card"];
var checkBoxes = [];
for (let i = 0; i < nodeTypes.length; i++) {
  checkBoxes.push(document.querySelectorAll('input[value="' + nodeTypes[i] + '"]')[0])
  checkBoxes[i].checked = true;
  checkBoxes[i].addEventListener("click", function() {
    filterBy("type", checkBoxes[i].value, checkBoxes[i].checked);
  });
}

var toggleOpacity = function(attribute, value, visible) {
  circles.filter(function(d) { //filter circles by attribute value
            return d[attribute] == value;
          })
          .each(function(d) { //modify visible attribute
            d.visible = visible;
          })
          .style("opacity", function(d) { // get opacity
            return getOpacity(d);
          });
  lines.filter(function(d) { // get links for attribute-value
            return d.source[attribute] == value || d.target[attribute] == value;
          })
          .style("opacity", function(d) { // modify opacity
            return getOpacity(d.source) && getOpacity(d.target) ? 1 : 0;
          })
}

var filterBy = function(attribute, value, visible, highlightSelected) {

  if (highlightSelected) {
     circles.style("opacity", 0)
     lines.style("opacity", 0)

        toggleOpacity(attribute, value, visible)

    circles.filter(function(d){return d.visible;}).transition()
      .duration(2000)
      .style("opacity", 1);

    lines.filter(function(d){return d.source.visible && d.target.visible}).transition()
      .duration(2000)
      .style("opacity", 1);
  }
    else{
    toggleOpacity(attribute, value, visible)
  }

}

当取消选中某些复选框时,现在突出显示节点似乎不起作用。

例如,当选中客户电话时,双击客户节点应仅显示相邻的客户电话节点。

但即使是其他不可见的邻近节点也会出现。

连接的节点()功能中,我尝试使用节点的可见属性。

 node.style("opacity", function (o) {
        return neighboring(d.visible, o.visible) | neighboring(o.visible, d.visible) ? 1 : 0.1;
    });

但这种方法似乎不起作用。

由于已经计算了可见属性的当前状态,因此只需使用它即可。但我正在努力做到这一点。仍然是我在d3.js的第一个项目,所以欣赏输入。

工作fiddle

1 个答案:

答案 0 :(得分:1)

其他过滤器处于活动状态时,所需的行为是什么?例如。当Customer单独处于活动状态(因此隐藏了其他节点)并双击客户时,是否要显示隐藏的邻居?

看看这个小提琴:https://jsfiddle.net/g0dm4q3n/1/ 我修改了connectedNodes函数,以便在单击d时调整相邻节点的不透明度,并根据visible属性恢复其不透明度 - 由其他过滤器设置。这样,当只检查了两个复选框时,例如,客户和电话,当您双击某个节点时,它会突出显示它的邻居(即使它们由于复选框而不可见),再次双击它会返回到之前的过滤状态。

function connectedNodes() {
    d = d3.select(this).node().__data__;
    // use d.clicked to save toggle
    if (!d.clicked) {
        //Reduce the opacity of all but the neighbouring nodes
        d.clicked = true;
        node.style("opacity", function (o) {
            // if they are neighboring set opacity to 1 
            // else 0.1 and do not change visible attribute
            return neighboring(d, o) || neighboring(o, d) 
                                                    ? 1 
                                                    : 0.1;
        });
        // you might want to indicate the clicked node maybe with a different border

        link.style("opacity", function (o) {
            return d.index==o.source.index | d.index==o.target.index ? 1 : 0.1;
        });
    } else {
        d.clicked = !d.clicked;
        //Put them back to opacity=1
        node.style("opacity", function(o){
            return o.visible? 1 :  0;
        });
        link.style("opacity", function(o){
            return o.target.visible && o.source.visible? 1:0;
        });
    }
}

您可能希望指示双击一个节点(请看一下:http://eutravel.clmsuk.com/semantics/graph - 它可以点击。同时,给它加载一些时间,因为有很多数据和很多事情都在那里:))以便用户知道该怎么做。

希望这有帮助!祝你好运!