2016-09-12 1 views
1

Je travaille sur this force graph dans D3 v4.Comment faire pour que seulement quelques bords réagissent à `mouseover` dans un graphe de force D3 v4

Lorsqu'un utilisateur clique sur un nœud, seuls les nœuds qui lui sont connectés deviennent visibles. De plus, les bords qui relient ces noeuds deviennent plus épais et les utilisateurs peuvent survoler le pour voir plus d'informations (l'info-bulle qui apparaît sur la droite).

Voilà comment je mettre en évidence les noeuds connectés après un clic

//Highlight on click 
function highlighting() { 
//Toggle stores whether the highlighting is on 
var node = d3.selectAll('circle'); 
var link = d3.selectAll('line'); 
var toggle = 0; 
//Create an array logging what is connected to what 
var linkedByIndex = {}; 
for (i = 0; i < dataset.nodes.length; i++) { 
    linkedByIndex[i + "," + i] = 1; 
}; 
d3.selectAll('line').each(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.0; 
     }); 
     link.style("opacity", function (o) { 
      return d.index==o.source.index | d.index==o.target.index ? 1 : 0.0; 
     }); 
     link.attr('stroke-width' , 4); 
     toggle = 1; 
     interactivityHighlight(); 

     //Change navigation div 
     d3.select('#click01').classed('hidden', true); 
     d3.select('#click02').classed('hidden', false); 

    } else { 
     //Put them back to starting opacity 
     node.style("opacity", 1); 
     link.style("opacity", function (d) {return edgeOpacityScale(d.collaborations);}); 
     link.attr('stroke-width', 1); 
     link.attr('class', null); 
     toggle = 0; 
     //Change navigation 
     d3.select('#click01').classed('hidden', false); 
     d3.select('#click02').classed('hidden', true); 
    } 
} 
node.on('click', connectedNodes); 
} 

Et ceci est la fonction que j'appelle après le clic

function interactivityHighlight() { 
graph.selectAll('line').on('mouseover', function (d) { 
    if (d3.select(this).style('opacity') == 1) { 
     d3.select(this) 
     .attr('stroke', 'red') 
     .attr('stroke-width', 6); 

     d3.select('#tooltip') 
     .classed('hidden', false); 

     d3.select('#tooltip') 
     .append('p') 
     .attr('id', 'org_names') 
     .text('Collaborations between ' + d.source.name + ' and ' + d.target.name); 

     d3.select('#tooltip') 
     .append('p') 
     .attr('id', 'collaborations') 
     .text('Worked together on ' + d.collaborations + ' projects'); 

     d3.select('#tooltip') 
     .append('p') 
     .attr('id', 'collBudget') 
     .text('Total budget: '+ commafy(d.collBudget)); 
}}) 

graph.selectAll('line').on('mouseout', function (d) { 
    if (d3.select(this).style('opacity') == 1) { 
     d3.select(this) 
     .attr('stroke', 'black') 
     .attr('stroke-width', 4); 

     d3.select('#tooltip') 
     .selectAll('p') 
     .remove(); 

     d3.select('#tooltip') 
     .classed('hidden', true); 
}}) 
} 

Fondamentalement, tous les nœuds non connectés obtenir opacity=0 et devenir ainsi invisible. Cependant, ils sont toujours présents sur le graphique: le survol d'une ligne ne peut pas déclencher interactivityHighlight() car la souris survole réellement un bord invisible.

Y a-t-il un moyen de faire disparaître les bords invisibles, ou de faire en sorte que les signes visibles "prennent le dessus" sur tous les autres?

Répondre

0

Utilisez la même règle que celle que vous avez utilisée pour définir "opacity" pour définir "pointer-events":

link.attr("pointer-events", function (o) { 
     return d.index==o.source.index | d.index==o.target.index ? "all" : "none"; 
    }); 
2

Ajouter une classe css qui comprend ce pointeur-événements règle par exemple:

.hidden { 
    pointer-events: none; 
} 

Et puis définissez cette classe sur les liens

.classed("hidden", function(d) { 
    /* return true/false, decide using the same logic you use for opacity */ 
}); 

Liens avec la classe cachée laissera des événements de pointeur passent à travers