Realce o nó selecionado, seus links e seus filhos em um gráfico direcionado à força D3

Eu estou trabalhando em um gráfico direcionado por força em D3. Quero destacar o nó mouseover’d, seus links e seus nós filhos definindo todos os outros nós e vinculando a uma opacidade mais baixa.

Neste exemplo, http://jsfiddle.net/xReHA/ , sou capaz de eliminar todos os links e nós e, em seguida, desaparecer nos links conectados, mas, até agora, não consegui desvanecer elegantemente nós conectados que são filhos do nó atual do mouse.

Esta é a function chave do código:

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); }); }; } 

Estou recebendo um erro Uncaught TypeError: Cannot call method 'setProperty' of undefined erro Uncaught TypeError: Cannot call method 'setProperty' of undefined quando tento definir a opacidade em um elemento carregado do source.target. Eu suspeito que este não é o caminho certo para carregar esse nó como um object d3, mas não consigo encontrar outra maneira de carregá-lo sem iterar sobre todos os nós novamente para encontrar os que correspondem ao destino do link ou fonte. Para manter o desempenho razoável, não quero iterar todos os nós mais do que o necessário.

Tomei o exemplo de desvanecer os links de http://mbostock.github.com/d3/ex/chord.html :

insira a descrição da imagem aqui

No entanto, isso não mostra como alterar os nós filhos conectados.

Quaisquer boas sugestões sobre como resolver ou melhorar isso serão furiosamente upvoted 🙂

O erro é porque você está selecionando os objects de dados (d.source e d.target) em vez dos elementos DOM associados a esses objects de dados.

Você tem a linha destacando o trabalho, mas eu provavelmente combinaria seu código em uma única iteração, assim:

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

Destacar os nós vizinhos é mais difícil porque o que você precisa saber os vizinhos para cada nó. Essas informações não são tão fáceis de determinar com suas estruturas de dados atuais, já que todas elas são uma matriz de nós e uma matriz de links. Esqueça o DOM por um segundo e pergunte-se como você determinaria se dois nós a e b são vizinhos?

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

Uma maneira cara de fazer isso é fazer uma iteração de todos os links e ver se existe um link que conecte aeb:

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

(Isso pressupõe que os links não são direcionados. Se você quiser destacar somente os vizinhos conectados diretamente, elimine a segunda metade da sala de cirurgia.)

Uma maneira mais eficiente de calcular isso, se você tiver que fazer isso com frequência, é ter um mapa ou uma matriz que permita uma consulta de tempo constante para testar se a e b são vizinhos. Por exemplo:

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

Agora você pode dizer:

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

E assim, agora você pode iterar nos nós e atualizar sua opacidade corretamente:

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

(Você também pode querer usar um link especial para o linkedByIndex , definindo um link próprio para cada nó em linkedByIndex , ou testando diretamente d ao calcular o estilo, ou usando um importante estilo css :hover .)

A última coisa que eu mudaria em seu código é usar opacidade de preenchimento e opacidade de traçado, em vez de opacidade, porque eles oferecem um desempenho muito melhor.

Intereting Posts