I need to be able to draw graphs like the following in JavaScript:
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?
In this article, we would be implementing the Binary Search Tree data structure in Javascript. A tree is a collection of nodes connected by some edges. A tree is a non linear data structure.
A tree is a data structure where a node can have zero or more children. Each node contains a value. Like graphs, the connection between nodes is called edges. A tree is a type of graph, but not all graphs are trees (more on that later).
A real world example of a tree data structure is the HTML Document Object Model (DOM) structure.
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.
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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With