2016-09-12 2 views
1

Ich arbeite an this force graph in D3 v4.Wie nur einige Kanten in einem D3 v4 Kraftdiagramm auf "mouseover" reagieren

Wenn ein Benutzer auf einen Knoten klickt, werden nur die Knoten sichtbar, die damit verbunden sind. Darüber hinaus werden die Kanten, die diese Knoten verbinden, dicker und Benutzer können auf dem Bildschirm schweben, um weitere Informationen zu sehen (der Tooltip, der auf der rechten Seite erscheint).

Dies ist, wie ich den angeschlossenen Knoten nach einem Klick

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

Und dies ist die Funktion, die ich nach dem Klick

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

Grundsätzlich sind alle nicht-verbundene Knoten opacity=0 nennen markierte erhalten und somit wurde unsichtbar. Sie sind jedoch immer noch in der Grafik vorhanden: Wenn Sie über eine Linie schweben, wird möglicherweise kein interactivityHighlight() ausgelöst, da die Maus tatsächlich über einer unsichtbaren Kante schwebt.

Gibt es einen Weg, wie ich die unsichtbaren Ränder wirklich verschwinden lassen kann, oder die sichtbaren "auf die Spitze" aller anderen bringen kann?

Antwort

0

Verwenden Sie die gleiche Regel, die Sie verwendet haben, um "Opazität" für die Definition "Zeiger-Ereignisse" zu definieren:

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

eine CSS-Klasse hinzufügen, die diese Zeiger-Ereignisse Regel zB beinhaltet:

.hidden { 
    pointer-events: none; 
} 

Und dann setzt diese Klasse auf den

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

Verbindungen mit der versteckten Klasse Links werden Zeiger Ereignisse passieren lassen durch zu nichts unter