2013-07-24 2 views
5

Я создал диаграмму, ориентированную на силу с плагином d3.js, и хочу покрасить узлы и метки с разным цветом в соответствии с группой, к которой они принадлежат.D3.js сила направленного графика, каждая группа разного цвета?

Я добавил шкалу цвета:

var color = d3.scale.category20(); 

и к узлу переменной я добавил:

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

, но все узлы находятся в том же цвете ..

Здесь это моя текущая ситуация: http://jsfiddle.net/WBkw9/

полный сценарий:

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

Что мне не хватает для разных цветов в каждой группе?

ответ

3

Ваша проблема в том, что group не определен для данных. В результате все ваши узлы окрашены для группы «undefined». Ваши круги определены для данных в force.nodes(), которые имеют следующие атрибуты: indexnamepxpyweightx и y. group определяется только для ссылок, для которых никогда не применяется цвет.

Как и в настоящее время, также нет четкого способа определить, какой цвет должен быть на узле. Что произойдет, если к узлу подключено несколько ссылок, и эти ссылки находятся в разных группах?

0

Я думаю, вам нужно изменить атрибут стиля круга, а не элемент g.

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

Редактировать: свойство группы в данных также должно быть заменено целыми числами или сделать позже.

+0

это просто изменяет окраску таким образом, так что только узел окрашен, а не весь текст. Но все же это не решает мою проблему, http://jsfiddle.net/F2fbu/. Я хочу, чтобы каждая группа была по-разному окрашена, теперь мне кажется, что я не могу сделать это с такими данными, потому что мне нужно указать, какая группа - какой узел ... – dzordz

+0

Группа должна быть целым числом, а не строкой. 'd3.selectAll (" circle "). style (" fill ", function (d) {return color (9)}) * изменил цвет всех кругов. – user4815162342

0

Вы когда-нибудь решали это? если не возможное решение здесь: http://jsfiddle.net/adeaver/F2fbu/1/

Каждая группа/узел по-разному окрашенные вместе с соответствующим текстом, добавив: .style("fill", function(d) { return color(d.group); }) к текстовому Append и group: link.group к функции, которая вычисляет узлы из звеньев

4

Вот мой код (на основе http://bl.ocks.org/mbostock/4062045). Он работает отлично. Вы можете увидеть, как это выглядит здесь: http://jsfiddle.net/Rom2BE/H2PkT/

Каждая группа имеет другой цвет.

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

Ваша информация группа доступна только в links объекте, как @ckersch уже указывал. Вам нужно будет добавить информацию о группе к вам nodes объект тоже. Для этого примера, что может быть сделано путем изменения линии 16 в:

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

Но для более сложных данных, с более чем одним source, все источники будут иметь тот же цвет (или это будет хорошо?).

Я сделал это изменение в этой скрипке: http://jsfiddle.net/WBkw9/19/.

Смежные вопросы