使用JavaScript/d3读取DOT文件

35

是否有一种标准方法可以在JavaScript中读取和解析DOT图形文件,最好的方式是能够与d3良好地配合使用?

目前,我所能想到的唯一做法就是读取纯文本并进行自己的解析。但希望这不会重复造轮子。

d3.text("graph.dot", function(error, dotGraph) {
    ....
)};

你看过graphlib-dot吗? - Lars Kotthoff
是的,但是我还没有能够让它工作。 - ajwood
4个回答

43

⚠ 这里提出的解决方案依赖于两个被其作者标记为不受支持的库。

要在Javascript中渲染Graphviz DOT文件,请将 graphlib-dotdagre-d3 库相结合。

graphlibDot.read() 方法接受用DOT语法定义的图形或有向图形,并生成一个图形对象。然后,dagreD3.render() 方法可以将该图形对象输出到SVG。

您可以使用其他D3方法向图形添加功能,根据需要从graphlib图形对象检索其他节点和边属性。

以下是一个微不足道的自包含示例:

window.onload = function() {
  // Parse the DOT syntax into a graphlib object.
  var g = graphlibDot.read(
    'digraph {\n' +
    '    a -> b;\n' +
    '    }'
  )

  // Render the graphlib object using d3.
  var render = new dagreD3.render();
  render(d3.select("svg g"), g);


  // Optional - resize the SVG element based on the contents.
  var svg = document.querySelector('#graphContainer');
  var bbox = svg.getBBox();
  svg.style.width = bbox.width + 40.0 + "px";
  svg.style.height = bbox.height + 40.0 + "px";
}
svg {
  overflow: hidden;
}
.node rect {
  stroke: #333;
  stroke-width: 1.5px;
  fill: #fff;
}
.edgeLabel rect {
  fill: #fff;
}
.edgePath {
  stroke: #333;
  stroke-width: 1.5px;
  fill: none;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://dagrejs.github.io/project/graphlib-dot/v0.6.4/graphlib-dot.min.js"></script>
<script src="https://dagrejs.github.io/project/dagre-d3/v0.5.0/dagre-d3.min.js"></script>

<html>

<body>
  <script type='text/javascript'>
  </script>
  <svg id="graphContainer">
    <g/>
  </svg>
</body>

</html>


这看起来很不错!但是我在使用你的示例时遇到了一个问题...我的图形比屏幕大,而且没有滚动条可以移动..有什么简单的方法可以解决吗? - ajwood
你需要设置SVG元素的宽度和高度。我还没有找到一种真正好的方法从图形内容自动设置它们,所以我目前将它们设置为非常大的值,或者使用试错法。 - Richard Neish
我的图表是动态生成的,因此从内容中找出它们肯定很不错。如果我想到了什么,我会告诉你的! - ajwood
2
我已经在Firefox和Chrome中测试成功,但还没有进行全面测试。在渲染图形后,在SVG元素上调用getBBox()以获取内容的边界框,然后根据边界框加上任何填充设置style.width和style.height属性。我将更新示例以反映这一点。 - Richard Neish
太好了!你如何将var g更改为从文件中读取?类似这样吗:fs.readFileSync('graph.dot', 'UTF-8') - sAguinaga
@sAguinaga 这是一个不同的问题。我建议你尝试一些方法,看看遇到了什么问题,寻找解决方案,如果没有找到答案,再提出另一个问题。 - Richard Neish

11

虽然来晚了,但如果您仍然感兴趣,这里有一种使用我刚刚发布的新的d3-graphviz插件来完成的方法:

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="http://viz-js.com/bower_components/viz.js/viz-lite.js"></script>
<script src="https://github.com/magjac/d3-graphviz/releases/download/v0.0.4/d3-graphviz.min.js"></script>
<div id="graph" style="text-align: center;"></div>
<script>

d3.select("#graph").graphviz()
    .renderDot('digraph  {a -> b}');

</script>


感谢@magjac(以及d3-graphgiz插件)发布此片段!我认为第一个<script>标签前面缺少了https - rambo
感谢。问题已经解决。但是,现在我遇到了一个我不理解的 https://github.com/magjac/d3-graphviz/releases/download/v0.0.4/d3-graphviz.min.js 的错误。 - magjac
.@magjac 嗯,我这边没有遇到同样的问题...也许是你机器上的证书问题,因为该网址使用https? - rambo
除了示例无法运行之外,我已经测试过它是最佳解决方案,它保留了图形的格式。 - Zain Ul Abidin
@magjac,你的库也能读取 JSON 吗? - joshlsullivan
1
@joshlsullivan 不,它只能读取DOT源文件。 - undefined

4

同一示例,使用最新版本的graphlib-dot和dagre-d3。

window.onload = function() {
      // Parse the DOT syntax into a graphlib object.
      var g = graphlibDot.read(
        'digraph {\n' +
        '    a -> b;\n' +
        '    }'
      )

      // Render the graphlib object using d3.
      var renderer = dagreD3.render();
      d3.select("svg g").call(renderer, g);


      // Optional - resize the SVG element based on the contents.
      var svg = document.querySelector('#graphContainer');
      var bbox = svg.getBBox();
      svg.style.width = bbox.width + 40.0 + "px";
      svg.style.height = bbox.height + 40.0 + "px";
    }
svg {
  overflow: hidden;
}
.node rect {
  stroke: #333;
  stroke-width: 1.5px;
  fill: #fff;
}
.edgeLabel rect {
  fill: #fff;
}
.edgePath {
  stroke: #333;
  stroke-width: 1.5px;
  fill: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="http://cpettitt.github.io/project/graphlib-dot/latest/graphlib-dot.min.js"></script>
<script src="http://cpettitt.github.io/project/dagre-d3/latest/dagre-d3.js"></script>

    <html>

    <body>
      <script type='text/javascript'>
      </script>
      <svg id="graphContainer">
        <g/>
      </svg>
    </body>

    </html>


这个更新后的代码可以工作,但是DOT文件输出的svg渲染非常依赖于节点和边的解析顺序。较旧的版本似乎可以无问题地渲染DOT文件。 - Bob Jordan

4
问题是要求在javascript或D3js中可视化.dot文件的可能性。我认为,最高评分答案的解决方案将适用于大多数人。
我不满意的原因有三个:
1.它除了D3js之外还涉及到像lowdash、dagre和graphlib这样的库,而且很重。 2.解析器输出不是D3js“友好”的数据结构。 3.使用(API)不符合D3js的风格。
这就是为什么我创建了一个适配器,基本上允许您通过改变一个语句来使用任何数以千计的D3js示例中的.dot文件。如果您有一些D3js可视化工作在以下数据结构上:
{
  "nodes": [ {"id": "Myriel"}, {"id": "Napoleon"}],
  "links": [ {"source": "Myriel"}, {"target": "Napoleon"}]
} 

只需包含以下脚本并调用d3.dot:

<script src="https://cdn.jsdelivr.net/gh/gmamaladze/d3-dot-graph@1.0.0/build/d3-dot-graph.min.js"></script>
<script>

d3.dot(url, function(graph) {
   ...
});

</script>

改为:

d3.json(url, function(graph) {...});

GitHub代码和示例的存储库


这正是我一直在寻找的。我很惊讶这里有2.5k行代码。太棒了 - 我会尝试一下,如果它有效,我会向其他人谈论它,因为我尝试过的许多其他路线,就像你所说的,都涉及无数依赖项。这值得更广泛的“可见性”;-) - Thomas Browne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接