在D3强制指示图中突出显示所选节点及其链接和子节点

我正在研究D3中的一个有向图。 我想通过将所有其他节点和链接设置为较低的不透明度来突出显示mouseover'd节点,其链接及其子节点。

在这个例子中,我可以淡出所有的链接和节点,然后淡入连接的链接,但到目前为止,我还没有能够优雅地淡入淡出连接的节点是当前鼠标hover节点的子节点。

这是代码中的关键function:

function fade(opacity) { return function(d, i) { //fade all elements svg.selectAll("circle, line").style("opacity", opacity); var associated_links = svg.selectAll("line").filter(function(d) { return d.source.index == i || d.target.index == i; }).each(function(dLink, iLink) { //unfade links and nodes connected to the current node d3.select(this).style("opacity", 1); //THE FOLLOWING CAUSES: Uncaught TypeError: Cannot call method 'setProperty' of undefined d3.select(dLink.source).style("opacity", 1); d3.select(dLink.target).style("opacity", 1); }); }; } 

我得到一个Uncaught TypeError: Cannot call method 'setProperty' of undefined当我尝试在从source.target加载的元素上设置不透明度时, Uncaught TypeError: Cannot call method 'setProperty' of undefined错误的Uncaught TypeError: Cannot call method 'setProperty' of undefined 。 我怀疑这不是正确的方式来加载该节点作为D3对象,但我找不到另一种方式来加载它没有遍历所有的节点再次find匹配的链接的目标或来源。 为了保持性能合理,我不想迭代所有节点超过必要的。

我采取了从http://mbostock.github.com/d3/ex/chord.html淡化链接的例子:

在这里输入图像描述

但是,这并不显示如何更改连接的子节点。

任何好的build议,如何解决或改善这将是愤怒upvoted 🙂

这个错误是因为你正在select数据对象(d.source和d.target)而不是与这些数据对象相关的DOM元素。

你已经有了突出显示的工作,但我可能会将你的代码合并成一个迭代,就像这样:

  link.style("opacity", function(o) { return o.source === d || o.target === d ? 1 : opacity; }); 

突出显示相邻节点比较困难,因为您需要知道每个节点的邻居。 这个信息并不是那么容易用你现在的数据结构来决定的,因为你所拥有的全是节点数组和链接数组。 忘了DOM一秒钟,问自己如何确定两个节点ab是否是邻居?

 function neighboring(a, b) { // ??? } 

一个昂贵的方法是遍历所有的链接,看看是否有连接a和b的链接:

 function neighboring(a, b) { return links.some(function(d) { return (d.source === a && d.target === b) || (d.source === b && d.target === a); }); } 

(假定链接是无向的,如果你只想突出显示正向连接的邻居,那么消除OR的后半部分。)

一个更有效的计算方法是,如果你经常这样做的话,就是有一个映射或者一个matrix,这个映射或者一个matrix允许定时查找来testinga和b是否是邻居。 例如:

 var linkedByIndex = {}; links.forEach(function(d) { linkedByIndex[d.source.index + "," + d.target.index] = 1; }); 

现在你可以说:

 function neighboring(a, b) { return linkedByIndex[a.index + "," + b.index]; } 

因此,您现在可以迭代节点并正确更新其不透明度:

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

(你也可能希望通过为linkedByIndex每个节点设置一个自连接,或者在计算样式时直接对d进行testing,或者使用!important css :hover样式来特殊设置鼠标hover链接本身。

在代码中,最后一件事情就是使用fill-opacity和stroke-opacity而不是opacity,因为这些提供了更好的性能。

Interesting Posts