2013-07-24 9 views
5

Ho creato un grafo forzato con il plugin d3.js e voglio colorare i nodi e le etichette con il colore diverso in base al gruppo a cui appartengono.D3.js forza il grafico diretto, ogni gruppo di colore diverso?

ho scala aggiunto per il colore:

var color = d3.scale.category20(); 

e al nodo variabile ho aggiunto:

.style("fill", function(d) { return color(d.group); }) 

ma tutti i nodi sono nello stesso colore ..

Qui è la mia situazione attuale: http://jsfiddle.net/WBkw9/

full script:

var links = [ 
    {source: "John", target: "Mike", group: "5"}, 
    {source: "John", target: "Janice", group: "5"}, 
    {source: "John", target: "Caleb", group: "5"}, 
    {source: "John", target: "Anna", group: "4"}, 
    {source: "John", target: "Tommy", group: "3"}, 
    {source: "John", target: "Jack", group: "2"}, 
    {source: "John", target: "Vilma", group: "1"}, 
]; 

var nodes = {}; 

// Compute the distinct nodes from the links. 
links.forEach(function(link) { 
    link.source = nodes[link.source] || (nodes[link.source] = {name: link.source}); 
    link.target = nodes[link.target] || (nodes[link.target] = {name: link.target}); 
}); 

var color = d3.scale.category20(); 

var width = 960, 
    height = 500; 

var force = d3.layout.force() 
    .nodes(d3.values(nodes)) 
    .links(links) 
    .size([width, height]) 
    .linkDistance(60) 
    .charge(-300) 
    .on("tick", tick) 
    .start(); 

var svg = d3.select("body").append("svg") 
    .attr("width", width) 
    .attr("height", height); 

var link = svg.selectAll(".link") 
    .data(force.links()) 
    .enter().append("line") 
    .attr("class", "link"); 

var node = svg.selectAll(".node") 
    .data(force.nodes()) 
    .enter().append("g") 
    .attr("class", "node") 
    .style("fill", function(d) { return color(d.group); }) 
    .on("mouseover", mouseover) 
    .on("mouseout", mouseout) 
    .call(force.drag); 

node.append("circle") 
    .attr("r", 8); 

node.append("text") 
    .attr("x", 12) 
    .attr("dy", ".35em") 
    .text(function(d) { return d.name; }); 

function tick() { 
    link 
     .attr("x1", function(d) { return d.source.x; }) 
     .attr("y1", function(d) { return d.source.y; }) 
     .attr("x2", function(d) { return d.target.x; }) 
     .attr("y2", function(d) { return d.target.y; }); 

    node 
     .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 
} 

function mouseover() { 
    d3.select(this).select("circle").transition() 
     .duration(750) 
     .attr("r", 16); 
} 

function mouseout() { 
    d3.select(this).select("circle").transition() 
     .duration(750) 
     .attr("r", 8); 
} 

cosa mi manca per colore diverso su ciascun gruppo?

risposta

3

Il tuo problema è che group non è definito per i tuoi dati. Di conseguenza, tutti i nodi sono colorati per il gruppo "non definito". Le tue cerchie sono definite per i dati in force.nodes(), che hanno gli attributi indexnamepxpyweightx e . group è definito solo per i collegamenti, a cui non è mai stato applicato il colore.

Allo stato attuale, non esiste anche un modo chiaro per determinare quale colore deve essere un nodo. Cosa succede se più di un collegamento si connette a un nodo e questi collegamenti sono in gruppi diversi?

0

Penso che sia necessario modificare l'attributo di stile del cerchio, non l'elemento g.

node.append("circle").style("fill", function(d) { return color(d.group); }) 

Modifica: la proprietà di gruppo nei dati deve anche essere cambiata in numeri interi o convertita in seguito.

+0

questo cambia solo colorando in questo modo in modo che solo il nodo sia colorato e non il testo del tutto. Ma ancora questo non risolve il mio problema, http://jsfiddle.net/F2fbu/. Voglio che ogni gruppo venga colorato in modo diverso, ora mi sembra di non poterlo fare con quel tipo di dati, perché ho bisogno di specificare quale gruppo è quale nodo ... – dzordz

+0

Il gruppo deve essere un numero intero, non una stringa. 'd3.selectAll (" circle "). style (" fill ", function (d) {return color (9)})' ha cambiato il colore di tutti i cerchi. – user4815162342

0

Hai mai risolto questo? se non una possibile soluzione è qui: http://jsfiddle.net/adeaver/F2fbu/1/

Ogni gruppo/nodo è di colore diverso insieme al testo corrispondente aggiungendo: .style("fill", function(d) { return color(d.group); }) al accodamento testo e group: link.group alla funzione che calcola i nodi dai link

4

Ecco il mio codice (basato su http://bl.ocks.org/mbostock/4062045). Funziona perfettamente. Puoi vedere come appare qui: http://jsfiddle.net/Rom2BE/H2PkT/

Ogni gruppo ha un colore diverso.

**index.html** 

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 

.node { 
    stroke: #fff; 
    stroke-width: 1.5px; 
} 

.link { 
    stroke: #999; 
    stroke-opacity: .6; 
} 

</style> 
<body> 
<script src="http://d3js.org/d3.v3.min.js"></script> 
<script> 

var width = 650, 
    height = 700; 

var color = d3.scale.category10(); 

var force = d3.layout.force() 
    .charge(-120) 
    .linkDistance(30) 
    .size([width, height]); 

var svg = d3.select("body").append("svg") 
    .attr("width", width) 
    .attr("height", height); 

d3.json("data.json", function(error, graph) { 
    force 
     .nodes(graph.nodes) 
     .links(graph.links) 
     .start(); 

    var link = svg.selectAll(".link") 
     .data(graph.links) 
    .enter().append("line") 
     .attr("class", "link") 
     .style("stroke-width", function(d) { return Math.sqrt(d.value); }); 

    // You define here your nodes and the color will be d.group 
    var node = svg.selectAll(".node") 
     .data(graph.nodes) 
    .enter().append("circle") 
     .attr("class", "node") 
     .attr("r", 5) 
     .style("fill", function(d) { return color(d.group); }) 
     .call(force.drag); 

    //Display node name when mouse on a node 
    node.append("title") 
     .text(function(d) { return d.name; }); 

    //Where and how nodes are displayed 
    force.on("tick", function() { 
    node.attr("cx", function(d) { return d.x; }) 
     .attr("cy", function(d) { return d.y; }); 

    link.attr("x1", function(d) { return d.source.x; }) 
     .attr("y1", function(d) { return d.source.y; }) 
     .attr("x2", function(d) { return d.target.x; }) 
     .attr("y2", function(d) { return d.target.y; }); 
    }); 

    //Legend 
    var legend = svg.selectAll(".legend") 
     .data(color.domain()) 
    .enter().append("g") 
     .attr("class", "legend") 
     .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }); 

    legend.append("rect") 
     .attr("x", width - 18) 
     .attr("width", 18) 
     .attr("height", 18) 
     .style("fill", color); 

    legend.append("text") 
     .attr("x", width - 24) 
     .attr("y", 9) 
     .attr("dy", ".35em") 
     .style("text-anchor", "end") 
     .text(function(d) { return d; }); 
}); 

</script> 


**data.json** 

{"nodes":[ 
    {"name":"Vertex 5","group":"Virtuals-MacBook-Pro-36095"},{"name":"Vertex 9","group":"Virtuals-MacBook-Pro-36095"},{"name":"Vertex 15","group":"Virtuals-MacBook-Pro-3-53688"},{"name":"Vertex 20","group":"Virtuals-MacBook-Pro-36095"},{"name":"Vertex 26","group":"Virtuals-MacBook-Pro-4-40842"},{"name":"Vertex 29","group":"Virtuals-MacBook-Pro-36095"},{"name":"Vertex 33","group":"Virtuals-MacBook-Pro-36095"},{"name":"Vertex 37","group":"Virtuals-MacBook-Pro-36095"},{"name":"Vertex 49","group":"Virtuals-MacBook-Pro-3-53688"},{"name":"Vertex 52","group":"Virtuals-MacBook-Pro-4-40842"},{"name":"Vertex 53","group":"Virtuals-MacBook-Pro-4-40842"},{"name":"Vertex 58","group":"Virtuals-MacBook-Pro-36095"},{"name":"Vertex 59","group":"Virtuals-MacBook-Pro-4-40842"},{"name":"Vertex 65","group":"Virtuals-MacBook-Pro-4-40842"},{"name":"Vertex 73","group":"Virtuals-MacBook-Pro-4-40842"},{"name":"Vertex 74","group":"Virtuals-MacBook-Pro-36095"},{"name":"Vertex 80","group":"Virtuals-MacBook-Pro-36095"},{"name":"Vertex 84","group":"Virtuals-MacBook-Pro-4-40842"},{"name":"Vertex 87","group":"Virtuals-MacBook-Pro-4-40842"},{"name":"Vertex 99","group":"Virtuals-MacBook-Pro-4-40842"} 
], 
"links":[ 
    {"source":5,"value":1,"target":11},{"source":5,"value":1,"target":12},{"source":10,"value":1,"target":12},{"source":11,"value":1,"target":5},{"source":11,"value":1,"target":12},{"source":11,"value":1,"target":14},{"source":12,"value":1,"target":5},{"source":12,"value":1,"target":10},{"source":12,"value":1,"target":11},{"source":14,"value":1,"target":11},{"source":16,"value":1,"target":19},{"source":18,"value":1,"target":19},{"source":19,"value":1,"target":16},{"source":19,"value":1,"target":18} 
]} 
1

vostro informazioni sul gruppo è disponibile solo nell'oggetto links, come @ckersch già sottolineato. Dovresti aggiungere anche le informazioni sul gruppo all'oggetto nodes. Per questo esempio che può essere fatto cambiando linea 16 in:

link.target = nodes[link.target] || (nodes[link.target] = {name: link.target, group: link.group}); 

Ma per i dati più complessi, con più di un source, tutte le fonti avrebbero lo stesso colore (o sarebbe che essere OK?).

Ho apportato questo cambiamento in questo Fiddle: http://jsfiddle.net/WBkw9/19/.

Problemi correlati