我有一个功能齐全的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
答案 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 - 它可以点击。同时,给它加载一些时间,因为有很多数据和很多事情都在那里:))以便用户知道该怎么做。
希望这有帮助!祝你好运!