【问题标题】:How do I find neighboring nodes & edges of all selected nodes ? D3如何找到所有选定节点的相邻节点和边缘? D3
【发布时间】:2014-12-18 12:39:25
【问题描述】:

我有一个力有向图,可以双击一个节点,只显示该节点及其邻居,其余的给定一个隐藏类 -> 可见性:隐藏

但这仅适用于一个节点。我有能力选择多个节点并给他们一个 selectedNode 类。

现在我希望在所有具有 selectedNode 类的节点上使用这种相邻算法。这样所有选定的节点和连接它们的边仍然会显示出来,而未选定的节点和边将被隐藏。

这是我显示/隐藏边缘的方式。同样,这只适用于一个节点d3.select(this).node().__data__;。我试过d = d3.selectAll("selectedNode").data(); 但没有运气:(

var linkedByIndex = {};//Create an array logging what is connected to what

for (i = 0; i < graph.data.nodes.length; i++) //-populate the array
{
    linkedByIndex[i + "," + i] = 1;
};


graph.data.edges.forEach(function (d) //-checks what nodes are related in array
{
    linkedByIndex[d.source.index + "," + d.target.index] = 1;
});


//-------------------------check if nodes are linked
function neighboring(a, b) //This function looks up whether a pair are neighbours
{
    return linkedByIndex[a.index + "," + b.index];
}

d = d3.select(this).node().__data__;


links.classed("hidden", function (o) {
            return d.index==o.source.index | d.index==o.target.index ? false : true;
        });

添加代码

var links = inner.selectAll(".link").append("g")
    .data(force.links())
    .enter().append("line")
    .attr("id", "links")
    .attr("class", "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; })
    .style("marker-end",  "url(#arrow)") //adds arrows, main code on SVG append towards bottom
    .style("stroke-width", lineWidth)   
    ;

【问题讨论】:

  • 你能提供一个带有 baerbone 实现的 jsfiddle 吗?目前尚不清楚this 在该范围内指的是什么。
  • 这里是基础知识,因为我的代码将近 1000 行长。 jsfiddle.net/reko91/skhhq62n/1。和 Lars 我已经看过了,但这仅适用于一个节点/线。如果可能,我想对多个节点执行此操作?
  • @LarsKotthoff 肯定有一种简单的应用方法:links.classed("hidden", function (o) { return d.index==o.source.index | d.index==o .target.index ? false : true; });到所有选定的节点而不是一个节点?

标签: javascript algorithm d3.js nearest-neighbor


【解决方案1】:

我认为这里有两个问题,由于您缺乏细节,我将做出假设。

1) 你有一个方法来检查两个节点是否是邻居。这是一个好的开始,但这还不够,您还需要一种方法来告诉您任何给定节点是选定节点还是它的邻居之一。假设您在数组selected 中维护一个选定节点的列表,下面是这样一个函数在一个简单的实现中的样子:

function shouldBeVisible(nodeIndex){
    // visible if either selected itself or neighbour of a selected node
    return selected.some(function(d){
        // assuming you don't care about the direction of your edges
        return linkedByIndex[nodeIndex+','+d]+linkedByIndex[d+','+nodeIndex];
    });
}

您甚至可以重载此方法以使其“边缘友好”:

function shouldBeVisible(sourceIndex, targetIndex){
    if (targetIndex !== undefined)
        return shouldBeVisible(sourceIndex)
            && shouldBeVisible(targetIndex);
    else return selected.some(function(d){
        return linkedByIndex[sourceIndex+','+d]
             + linkedByIndex[d+','+sourceIndex];
    });
}

请注意,如果您不维护数据结构中的选定节点,您应该能够使用d3.selectAll('.selectedNode') 轻松检索它们。您可能希望为边缘实现类似的方法。

2) 您只是根据first node in the selection 而不是all nodes in the selection 检查邻域。无论哪种方式,假设links 准确地描述了它所指的内容,您都不必费心这样做。

试试这样的:

links.classed("hidden", function(d) {
    return !shouldBeVisible(d.source.index, d.target.index);
});

【讨论】:

  • 哇。很好的回应:) 干杯人。你说的是 d3.selectAll('.selectedNode'),我可以对节点执行此操作,但如果我要对边缘执行此操作,我将不得不查看边缘源和目标是否被归类为“selectedNode”我会怎么走关于那个?
  • 除非您将边缘分类为 .selectedEdge 或维护选定的边缘数据结构,否则我看不到直接的解决方法。
  • 这就是我想做的,就是给他们一个类,但要做到这一点,你必须检查它的源节点和目标节点,看看它们是否有一个可见或隐藏的类:/ :(跨度>
  • 我不确定我理解你的意思。您的 links 变量指的是什么?这不是您的链接选择吗?如果是,那么您的答案在 2)
  • 更新的代码@reno 不知道这是否有帮助:/ 我想要做的是如果链接源和目标是可见的,则显示链接,如果它们中的任何一个被隐藏,则不显示链接
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-27
  • 2016-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多