specifying colors for each link in a force directed network

5,885 views
Skip to first unread message

Dae Il Kim

unread,
Aug 13, 2011, 3:07:43 PM8/13/11
to d3-js
Hi guys,

A newbie at this so please bear with me, but I'm having some trouble
modifying each link color based off of some information in my data
associated with each link using the force directed layout. If there is
some kind of example where each link has some color assigned to it
given a dataset, that would work for me as well to save folks some
trouble. Here is the relevant data that I'm using as test:

"links":
[{"source":0, "target":1, "forward":98, "backward":100, "topic":1},
{"source":0, "target":2, "forward":19, "backward":100, "topic":1},
{"source":1, "target":3, "forward":38, "backward":100, "topic":2},
{"source":2, "target":4, "forward":19, "backward":100, "topic":2},
{"source":3, "target":2, "forward":15, "backward":100, "topic":2},
{"source":0, "target":6, "forward":19, "backward":100, "topic":3},
{"source":5, "target":4, "forward":29, "backward":100, "topic":3},
{"source":5, "target":8, "forward":49, "backward":100, "topic":4},
{"source":6, "target":7, "forward":19, "backward":100, "topic":1}]}

I can see the links and nodes when I specify a manual color, but I
want the links between nodes to change given the topic value:

Here is the relevant code. I'm wondering if accessing is d.topic is
not possible since assigning link data only evaluates the source and
target variables associated with links.:

d3.json("../data/dataFD-test.json", function(json) {
var force = self.force = d3.layout.force()
.nodes(json.nodes)
.links(json.links)
.gravity(.05)
.distance(function(d) {return d.forward;})
.charge(-150)
.size([w, h])
.start();

var linkpath = linkenter.append("svg:path")
.attr("class","link")
.attr("id", function(d) {return "path"+d.source.index
+"_"+d.target.index;})
---> .attr("stroke", function(d) {return "#"+ d.topic +"00";})
.attr("marker-end", function(d) {return
"url(#marker"+d.source.index+"_"+d.target.index+")"});


Thanks so much.

Peter Meehan

unread,
Aug 14, 2011, 6:45:23 PM8/14/11
to d3...@googlegroups.com
The force graph layout does only require the source and target properties to define the "links", but when it comes to defining the attributes for the lines that will represent these links (as  the second half of your code is doing), you can use any and all of the properties in your link data that you wish.

Actually, the problem with your code is just that "stroke" is a style property, not an attribute, so that line should read:
    .style("stroke", function(d) {return "#"+ d.topic +"00";})

By the way, you might want to use a different colour function, as that data will only translate to a colour range of "nearly-black" to "nearly-black-with-a-hint-of-red" :)
I assume the "topic" data is categorical, rather than quantitative? If so, D3 comes with a really elegant and easy to use colour scale function: https://github.com/mbostock/d3/wiki/Ordinal-Scales

All you need to do is declare the scale as a variable outside the function (let's call it "fill") as follows:
    var fill = d3.scale.category10();

Then replace the line in your code with this:
    .style("stroke", function(d) {return fill(d.topic);})

Simple as that!
This is how Mike coloured the nodes in his force graph example (http://mbostock.github.com/d3/ex/force.html)

If you ever need more than the 10 colours, just use d3.scale.category20() instead. And if you need more than 20... then you probably shouldn't be using a colour scale in the first place :)

Dae Il Kim

unread,
Aug 14, 2011, 9:18:41 PM8/14/11
to d3-js
Thanks so much Peter! That did the trick. :)
Reply all
Reply to author
Forward
0 new messages