Chr*_*ing 70 javascript highlight chord d3.js force-layout
我正在研究D3中的力导向图.我想通过将所有其他节点和链接设置为较低的不透明度来突出显示鼠标悬停节点,其链接及其子节点.
在这个例子中,http://jsfiddle.net/xReHA/,我能够淡出所有的链接和节点然后淡化连接的链接,但是,到目前为止,我还没有能够优雅地淡化连接的节点,它们是当前鼠标悬停节点的子节点.
这是代码中的关键功能:
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);
});
};
}
Run Code Online (Sandbox Code Playgroud)
Uncaught TypeError: Cannot call method 'setProperty' of undefined当我尝试在从source.target加载的元素上设置不透明度时,我收到错误.我怀疑这不是将该节点作为d3对象加载的正确方法,但我找不到另一种方法来加载它而不再遍历所有节点以找到与链接的目标或源匹配的节点.为了保持性能合理,我不希望迭代超过所有节点.
我以http://mbostock.github.com/d3/ex/chord.html上的链接淡化为例:

但是,这并未显示如何更改已连接的子节点.
任何有关如何解决或改善这一点的好建议都将被激烈地推崇:)
mbo*_*ock 90
错误是因为您正在选择数据对象(d.source和d.target)而不是与这些数据对象关联的DOM元素.
你有突出显示的工作,但我可能会将你的代码组合成一个迭代,如下所示:
link.style("opacity", function(o) {
return o.source === d || o.target === d ? 1 : opacity;
});
Run Code Online (Sandbox Code Playgroud)
突出显示相邻节点更难,因为您需要知道每个节点的邻居.使用您当前的数据结构并不容易确定此信息,因为您拥有的所有信息都是一组节点和一组链接.忘记了第二的DOM,并问自己,你将如何确定是否两个节点a,并b为邻?
function neighboring(a, b) {
// ???
}
Run Code Online (Sandbox Code Playgroud)
一种昂贵的方法是遍历所有链接并查看是否存在连接a和b的链接:
function neighboring(a, b) {
return links.some(function(d) {
return (d.source === a && d.target === b)
|| (d.source === b && d.target === a);
});
}
Run Code Online (Sandbox Code Playgroud)
(这假定链接是无向的.如果您只想突出显示前向连接的邻居,则消除OR的后半部分.)
如果你不得不经常这样做,一种更有效的计算方法是使用一个映射或矩阵,它允许进行恒定时间查找以测试a和b是否是邻居.例如:
var linkedByIndex = {};
links.forEach(function(d) {
linkedByIndex[d.source.index + "," + d.target.index] = 1;
});
Run Code Online (Sandbox Code Playgroud)
现在你可以说:
function neighboring(a, b) {
return linkedByIndex[a.index + "," + b.index];
}
Run Code Online (Sandbox Code Playgroud)
因此,您现在可以迭代节点并正确更新其不透明度:
node.style("opacity", function(o) {
return neighboring(d, o) ? 1 : opacity;
});
Run Code Online (Sandbox Code Playgroud)
(您可能还希望通过为每个节点设置自链接linkedByIndex,或者通过d在计算样式时直接测试,或者使用!important css :hover样式来特殊处理鼠标悬停链接本身.)
我在代码中要改变的最后一件事是使用填充不透明度和笔触不透明度而不是不透明度,因为它们提供了更好的性能.