“Force-horse”: Wrapping D3’s Force Layout in a component suitable for visual analysis of real-life data-sets


D3.js is an awesome open-source javascript library for building interactive data visualization layouts. D3’s “Force Layout” is a great implementation of forces and constraints based simulation – for building visual link analysis layouts.

However, exploring it in the last 2 years, we’ve discovered that using Force Layout as the main visual link analysis control in complex web applications for big data analysis, as the ones we develop at webiks, requires quite an effort. Especially when trying to use it for real world data-sets, describing human social behavior (SNA, Social Network Analysis).

So we’ve developed “force-horse”, a javascript component that wraps Force Layout and adds some functionalities that we found that are very useful, specifically:

  1. Adaptive tuning of forces and constraints parameters: Force Layout is quite sensitive to those somewhat mysterious parameters (gravity, charge, theta, alpha – to name a few). We found it quite a hassle to tune them manually whenever a new data-set is presented. So, we tuned them manually for some real-life data-sets, and then generalized the tuning mechanism into simple formulas that take into account network’s descriptors, such as the number of nodes and edges. While the result is not perfect, it is definitely reasonable and allows us to load very different networks and still get a reasonable visual result.  
  2. Adaptive rendering cycle: dealing with large networks costs. The iterative nature of the Force Layout simulation allows us to balance the trade-off between the animation’s smoothness and the loading time by correlating the rendering frame-rate to the network’s size. as the network gets bigger – we skip some rendering cycles thus shorten the loading time. Again – not perfect, but allowing us to deal with different data-sets (very small or quite large) in a single configuration.
  3. Play/Pause the simulation: inspired by Gephi, we’ve exposed the “sticky” functionality as a play/pause button, allowing the user to select whether he wants the interaction to be continuous (play) or only be used for initial network setup.
  4. Multiple edges between two nodes: real world graphs are usually “typed” – both the nodes and edges can be of different types (for example – “retweet”  and “quote” are two different types of edges in a typical twitter graph). So we’ve added the functionality for parallel lines between two nodes. You can read some more technical and mathematical details regarding this implementation here.
  5. Weight the nodes and the edges: a typical desired functionality is “weighting” the nodes according to a  centrality parameter (“degree centrality” in our case) – the more central the node is, the bigger its icon. When it comes to edges – the bigger the edge’s weight, the thicker the line that represents it.  



Force-horse is implemented as an angular.js 1.4 directive. It can be used either as an HTML element or as an HTML element attribute:

<force-horse options=”ctrl.options”></force-horse>


<div force-horse options=”ctrl.options”></div>

A force-horse element does not have an intrinsic size. It adapts itself to the size that is set from outside, in the surrounding HTML. force-horse is implementing CSS flex-box display logic.

Parameters are passed through the options attribute. Pass an object, which has to contain the property:

data: the graph data (nodes and links)

Force-horse writes into the options parameter the property:

forceHorseInstance: an object representing one directive instance (note that several instances of force-horse may be displayed simultaneously, and independently)

This instance property can be used by the application to register callbacks and/or to call callback apis of the directive. There are four available types of callbacks:

  • hover: a node/link is hovered upon
  • select: a node/link is selected
  • dblclick: a node/link is double-clicked upon
  • filter: remove the selected nodes/links from the graph

In addition, force-horse supports an external json file, forceHorse.json. In this file one can set whether each of the buttons (see below) is displayed or not. In addition, force layout parameters can be set, and thus to override the parameters that force-horse computes automatically, for a specific implementation.

The force-horse project contains a complete demo application. The demo application is also available on the plunker site.



On activation, force-horse shows the given graph. The graph stabilizes after a short force simulation. Then, if needed, it zooms out, so that the whole graph can be seen at a glance.

Beside showing the graph itself, force-horse provides visual indication of hovering over a node/link, and of selecting a node/link. It supports node dragging, and also pan and zoom.

In addition, force-horse is providing the following buttons:

  • filter: remove selected nodes/links from the graph.
  • pause/play: allows to “freeze” the graph, to locate nodes without subsequent changes by the force-layout simulation.
  • home: automatically pan/zoom so that the whole graph can be seen at a glance.
  • labels: show/hide node labels.
  • node weight: show/hide node weight (weightier nodes will be larger).
  • link weight: show/hide link weight (weightier links will be thicker).



The main dependencies of force-horse are:

  • angular.js v1.4
  • d3.js v3

A complete list can be found in file bower.json at the project’s root.



Force-horse was designed for high performance. Some of the measures in use are:

  • Minimal use of angular’s $watch’es.
  • Large graphs are not rendered continuously, but only a few times during the force simulation. The screen rendering is controlled programmatically, implementing javascript requestAnimationFrame(). A thin progress bar is displayed, during a force simulation, so that even if rendering is held, the user can know the stage and the pace of the current force simulation.



The ability to compute multiple, parallel link between two nodes is not currently supported intrinsically by d3.js. It was also not yet developed by the users community. Therefore, we developed this ability especially for force-horse. For the mathematical and implementation details, see here.



What’s next? We are thinking in the following directions:

  • Upgrade to D3 V4 – it’s Force Layout should be much better, at least performance-wise.
  • Add support to different layouts. Specifically – hierarchical trees.
  • Add support for the group/collapse behavior (nodes grouping, network folding, cluster visualization) – such as the ones demonstrated here and here.
  • Server-side data handling for dealing with real-world big-data networks.
  • “Ego network” selection.
  • Calculation and visualization of “the shortest path” between two selected nodes.
  • Support both “directed” and “undirected” graphs (current version visualizes both in an undirected manner).

Thinking about the same topic from a different perspective? Share your thoughts here in the comments!

Working on something similar? Contribute to our github project!

2 thoughts on ““Force-horse”: Wrapping D3’s Force Layout in a component suitable for visual analysis of real-life data-sets

Leave a Reply