2013-07-24 8 views
5

Ich habe eine Kraft gerichtete Grafik mit d3.js Plugin gemacht, und ich möchte die Knoten und die Etiketten mit der unterschiedlichen Farbe je nach Gruppe, die sie gehören, färben.D3.js Kraft gerichtete Grafik, jede Gruppe andere Farbe?

I Maßstab für Farbe hinzugefügt haben:

var color = d3.scale.category20(); 

und Variablen zu einem Knoten hinzugefügt haben:

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

aber alle Knoten sind in der gleichen Farbe ..

Hier ist meine aktuelle Situation: http://jsfiddle.net/WBkw9/

vollständige Skript:

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

Was fehlt mir an unterschiedlichen Farben in jeder Gruppe?

Antwort

3

Ihr Problem ist, dass group nicht für Ihre Daten definiert ist. Als Ergebnis werden alle Knoten für die Gruppe "undefiniert" eingefärbt. Ihre Kreise sind für die Daten in force.nodes() definiert, die die Attribute indexnamepxpyweightx und y haben. group ist nur für die Links definiert, auf die nie eine Farbe angewendet wurde.

Wie es derzeit steht, gibt es auch keine klare Möglichkeit, um festzustellen, welche Farbe ein Knoten haben soll. Was passiert, wenn mehr als ein Link mit einem Knoten verbunden ist und sich diese Links in verschiedenen Gruppen befinden?

0

Ich denke, dass Sie das Stilattribut des Kreises ändern müssen, nicht das g Element.

Edit: Die Gruppeneigenschaft in den Daten muss auch ganze Zahlen geändert werden oder später umgewandelt werden.

+0

Dies ändert nur die Färbung auf diese Weise, so dass nur der Knoten gefärbt ist und nicht der Text insgesamt. Aber das löst mein Problem nicht, http://jsfiddle.net/F2fbu/. Ich möchte, dass jede Gruppe anders gefärbt wird, jetzt scheint mir, dass ich das mit dieser Art von Daten nicht machen kann, weil ich spezifizieren muss welche Gruppe welcher Knoten ist ... – dzordz

+0

Die Gruppe muss eine ganze Zahl sein, keine Zeichenkette. 'd3.selectAll (" Kreis "). style (" fill ", Funktion (d) {return color (9)})' änderte die Farbe aller Kreise. – user4815162342

0

Haben Sie das jemals gelöst? wenn nicht eine mögliche Lösung ist hier: http://jsfiddle.net/adeaver/F2fbu/1/

Jede Gruppe/Knoten wird unterschiedlich mit dem entsprechenden Text gefärbt entlang durch Zugabe von: .style("fill", function(d) { return color(d.group); }) zum Text append und group: link.group auf die Funktion, die die Knoten aus den Verbindungen

4
berechnet

Hier ist mein Code (basierend auf http://bl.ocks.org/mbostock/4062045). Es funktioniert perfekt. Sie können sehen, wie es hier aussieht: http://jsfiddle.net/Rom2BE/H2PkT/

Jede Gruppe hat eine andere Farbe.

**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

Ihre Gruppeninformationen sind nur in dem links Objekt, wie @ckersch bereits hingewiesen. Sie müssten die Gruppeninformationen auch zu Ihrem nodes Objekt hinzufügen. Für dieses Beispiel, dass durch eine Änderung Leitung 16 in getan werden kann:

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

Aber für komplexere Daten, mit mehr als einem source, alle Quellen würde die gleiche Farbe (oder wäre das in Ordnung sein?).

Ich habe diese Änderung in dieser Fiddle gemacht: http://jsfiddle.net/WBkw9/19/.

Verwandte Themen