37

I need to be able to draw graphs like the following in JavaScript:

crazy graph picture

I know about the Raphael library, but it's only for drawing arbitrary shapes.

I have a few predefined node types (the colored nodes on the image) and text nearby/inside every node. This library doesn't seem to handle that case. How do I do this in JavaScript? If this has been accomplished already by another library, how can I use that library to solve this problem?

Lance Roberts
  • 22,383
  • 32
  • 112
  • 130
Alexey
  • 3,414
  • 7
  • 26
  • 44
  • 20
    closed as not constructive? This is a coding question, I came across it and would have loved the (updated 2016) answer. – Brian Leach Jan 19 '16 at 21:45
  • @BrianLeach That's how I ended up here, too, but that's sort of the point. The question was asked in 2013; that means that the answers that tend to be the most updated are the *older* ones that might not apply or work anymore, whereas the newest answers will have fewer votes. Plus they tend to attract promotional answers, etc. – Joshua Taylor Feb 25 '16 at 20:43
  • 1
    @JoshuaTaylor - that's a good point, and as such I've updated my answer to try and bring it up to date. The question doesn't really date that much but the answers can. – Ian Mar 22 '16 at 09:47
  • 3
    @Ian and JoshuaTaylor just wanted to thank you both for keeping this thread updated, even though it's closed. I'm sure the community (not only me as the author) appreciates that! – Alexey Mar 22 '16 at 13:07
  • 4
    Not...constructive? How is this possibly not constructive? I've actually been searching for just this question / answer for a while and this is extremely constructive. Man...stackoverflow mods just blow my mind sometimes. – Greg Blass Sep 27 '18 at 00:47

1 Answers1

61

The web is a fast moving world, and so this answer was somewhat out of date. With that in mind, I've refreshed this answer to make it applicable in 2016.

  • D3.js - This would still be my recommendation. It's under active development and has a vibrant community.
  • Vega - An expressive language (less powerful than D3)
  • Cytoscape.js
  • Spring.js
  • cola.js

I would add that I've only used D3.js in this new list, it's power and flexibility are such that I've never needed to find an alternative. Here is an example implementation of a force directed.

var width = 960,
    height = 500;

var color = d3.scale.category20();

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("https://gist.githubusercontent.com/mbostock/4062045/raw/4176c7d0c0c5ce15630d16072da0af67bb50eb6a/miserables.json", function(error, graph) {
  if (error) throw error;

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

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

  node.append("title")
      .text(function(d) { return d.name; });

  force.on("tick", function() {
    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("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  });
});
.node {
  stroke: #fff;
  stroke-width: 1.5px;
}

.link {
  stroke: #999;
  stroke-opacity: .6;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

There are a number of libraries for drawing this sort of output in a browser, you've mentioned Raphael, others include:

  • Sigma.js
  • Processing.js
  • jit.js - Sold to SenchaLabs. The solo developer appeared to stop working on it.
  • D3.js
  • Raphael.js - Seems to have disappeared, their main site has gone

I personally would recommend the latter, D3 depending on the number of items you wish to display and the browser support you need as it's well documented, powerful and faily easy to use. Check out this Github project for an example of a force-directed library.

The changes that you would need to make to accomplish the task you've set out would be to:

1) Change where the data is coming from by modifying the following function:

d3.json("flare.json", function(json) {
   root = json;
   root.fixed = true;
   root.x = w / 2;
   root.y = h / 2 - 80;
   update();
 });

Change the d3.json("flare.json") to point to a different file/URL on your server. It is possible to do the same thing with jQuery if you wished and use a similar callback approach.

2) To colour your nodes based on different categories you'll want to change the following section:

// Update the nodes…
  node = vis.selectAll("circle.node")
      .data(nodes, function(d) { return d.id; })
      .style("fill", color);

Change the .style("fill", color); to something along the lines of:

.style("fill", function(d) { 
    switch(d.category) {
       case A: return "#FF0000";
       case B: return "#00FF00";
       default: return "#0000FF";
    }
});

Where category is a property on the JSON data object that you want to vary by.

Ian
  • 33,605
  • 26
  • 118
  • 198
  • Thanks, Ian. I think I'll definitely select one of these! D3 also has an example I need – Alexey Apr 17 '13 at 13:11
  • 1
    @Alexey: Glad it helped. Sigma is the fastest but it's canvas based, D3 is SVG based and probably the most configurable from what I've seen. JIT is also Canvas and not being actively developed as far as I'm aware. I've no experience of Processing. – Ian Apr 17 '13 at 13:30
  • 9
    `How do I do this in JavaScript? If this has been accomplished already by another library, how can I use that library to solve this problem?` This just lists technologies, and does not explain how to solve the OP's question. – LittleBobbyTables - Au Revoir Apr 17 '13 at 18:41
  • 2
    @JoshCaswell: Although I disagree a little (It's took me quite some time to become aware of all the libraries to do this) you are right, it is all achievable with some searching so I've included some more details on the difference between an example and the result the question wants. Hopefully will get rid of some of those downvotes. – Ian Apr 18 '13 at 07:46
  • @LittleBobbyTables: I've updated my answer to hopefully make it more useful. – Ian Apr 18 '13 at 07:57
  • 1
    Ian, thanks for your update. Even though the question is closed now, I'm sure your edit was helpful. Indeed, I was asking only about certain tools and not how to use them (I'll read their doc). Thanks and sorry for downvotes you got, I voted up for it – Alexey Apr 18 '13 at 10:49
  • @Alexey: Lots of debate on http://meta.stackexchange.com/questions/176960/why-has-this-question-received-close-votes-when-it-perfectly-fits-the-faq about this question... thats why the downvotes. – Ian Apr 18 '13 at 14:33