JS library for displaying direct acyclic graphs (DAGs)
Asked Answered
M

3

17

I am trying to make a browser-based tool that lets you inspect dependency graphs as they appear in module systems of programming languages and Makefiles.

I am looking for a visualization framework that does the drawing for me.

The requirements are that the toolkit can

  • label nodes (and hopefully edges)
  • automatically space out the graph to the right size (I don't have to guess good dimensions) given that I have infinit space (scroll bars are fine)
  • layout the graph nicely so that it doesn't look as messy
  • be fine with <= 5000 nodes
  • run with JS only (no Flash or desktop apps)

Optionally, it would be nice if it made it easy to move nodes around and highlight or hide parts of the graph for better overview.

It does not matter much what backed is used (SVG, canvas, all fine).

I have looked at quite a few libraries so far (especially from Graph visualization library in JavaScript), but not found a fitting one yet:

  • d3 is nice but the only node-graph it delivers is a force graph, which is focused on real time physics. Once loaded, you have to wait and watch for the physics engine to stabilize. I don't need animations nor the Force, and want to show the graph right away.
  • GraphDracula's examples are pretty much what I am looking for, but already with 70 nodes and 400 edges, the drawing performance becomes really bad. It also has very little documentation (being a 35 line code example).

Do you know something that meets my requirements? Thanks!

Mario answered 20/5, 2013 at 10:24 Comment(1)
See also #7534Provide
B
2

In a commercial scenario you might want to consider yFiles for HTML:

Regarding your requirements it can:

  • Add any number of labels to nodes and edges
  • Provide virtually infinite scrolling/panning/zooming area
  • Layout your graph automatically using a great variety of automatic layout algorithms. For dependency graphs, the Hierarchic Layouter is very well suited
  • works nicely on desktop browsers with larger numbers of nodes. Depending on the visual complexity and graph structure, 5000 elements might proove difficult with todays browser implementations, though.
  • It's a pure Javascript library with no dependencies whatsoever
  • Uses SVG as the main backend, but can also leverage Canvas
  • The library is well documented, which is necessary given its complexity

Here is a screenshot showing some of the above features in action - the layout was calculated automatically:

enter image description here

Disclaimer: I work for the company that creates the library. On SO/SE I do not represent my employer. This is my own post.

Bayless answered 24/1, 2014 at 15:31 Comment(0)
S
1

Dagre works pretty well for graph layout (horizontal/vertical alignment, labels, etc.) and has D3 renderer.

https://github.com/cpettitt/dagre-d3 (check images at the end)

https://github.com/cpettitt/dagre

Syzran answered 3/11, 2013 at 2:9 Comment(1)
cytoscape.js can use the dagre layout library as well. see js.cytoscape.org/demos/e52c2fbc0b09edd6ec46Mitzvah
O
1

elkjs is a strong DAG-capable library. It has a lot of flexibility as can be seen in this live editor. A decent list of examples are shown as well.

example elkjs dag

If you're planning on using this in the browser (instead of a node application) make sure to also add web-worker as a development dependency:

pnpm add elkjs
pnpm add -D web-worker

To use it, you create an instance of the elk constructor, provide it your graph definition, then use the data that is returned from the Promise to draw the positioned data with your preferred rendering method.

import Elk from 'elkjs';

// ...

const elk = new Elk();

elk
  .layout({
    id: 'root',
    layoutOptions: { 'elk.algorithm': 'layered' },
    children: [
      { id: 'n1', width: 30, height: 30 },
      { id: 'n2', width: 30, height: 30 },
      { id: 'n3', width: 30, height: 30 }
    ],
    edges: [
      { id: 'e1', sources: [ 'n1' ], targets: [ 'n2' ] },
      { id: 'e2', sources: [ 'n1' ], targets: [ 'n3' ] }
    ]
  })
  .then((computedGraphData) => /* draw your data here */)
  .catch(console.error);

Where the data for the graph definition provided above is equivalent to:

{
  "id": "root",
  "layoutOptions": {
    "elk.algorithm": "layered"
  },
  "children": [
    {
      "id": "n1",
      "width": 30,
      "height": 30,
      "$H": 349,
      "x": 12,
      "y": 17
    },
    {
      "id": "n2",
      "width": 30,
      "height": 30,
      "$H": 351,
      "x": 62,
      "y": 12
    },
    {
      "id": "n3",
      "width": 30,
      "height": 30,
      "$H": 353,
      "x": 62,
      "y": 62
    }
  ],
  "edges": [
    {
      "id": "e1",
      "sources": [
        "n1"
      ],
      "targets": [
        "n2"
      ],
      "sections": [
        {
          "id": "e1_s0",
          "startPoint": {
            "x": 42,
            "y": 27
          },
          "endPoint": {
            "x": 62,
            "y": 27
          },
          "incomingShape": "n1",
          "outgoingShape": "n2"
        }
      ],
      "container": "root"
    },
    {
      "id": "e2",
      "sources": [
        "n1"
      ],
      "targets": [
        "n3"
      ],
      "sections": [
        {
          "id": "e2_s0",
          "startPoint": {
            "x": 42,
            "y": 37
          },
          "endPoint": {
            "x": 62,
            "y": 77
          },
          "bendPoints": [
            {
              "x": 52,
              "y": 37
            },
            {
              "x": 52,
              "y": 77
            }
          ],
          "incomingShape": "n1",
          "outgoingShape": "n3"
        }
      ],
      "container": "root"
    }
  ],
  "$H": 347,
  "x": 0,
  "y": 0,
  "width": 104,
  "height": 104
}

elkjs is also used in a few existing libraries such as:

Offering answered 28/1 at 7:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.