【翻译】Dagre-D3 文档整理和翻译

地址:
github Dagre-D3

目录

dagre-d3

Dagre是一个JavaScript库, 可以更轻易得在客户端布局连接图。此库是dagre的前端子库, 底层使用D3进行渲染。

如果要查看更多详细信息(包含样例和配置在内), 请查看wiki页面。

设计优先级

  1. 完全的客户端计算布局。如果客户端布局对你来说并非所需, 可以查看graphviz, 这是个功能丰富的代替品。

样式举例:
graph visualization of matrices from the University of Florida Collection

  1. 速度。Darge为了更快得绘制中等图像, kennel不会采用更合适、准确的算法。
  2. 渲染的不可知性。Darge仅需要非常基础的信息就能绘制图像,比如节点的维度。你可以自由地使用任何你喜欢的技术渲染图形。此处推荐学习d3

安装

npm

在安装这个库之前, 需要向安装npm
然后执行安装:

$ npm install dagre

Bower

$ bower install dagre

Browser Scripts

你可以获取到最新版的browser-ready版本文件:

你也可以指定下载版本, 通过realease page找到所需版本。

源代码构建

在构建之前, 需要先下载npm管理器。

在此项目的根目录下执行以下命令:

$ make dist

此命令会在当前项目的dist目录下生成dagre.js和dagre.min.js两个文件。

如何使用Darge

聚焦渲染

如上文提到, dagre仅聚焦于图像布局。 这意味着你需要使用dagre的布局信息来渲染图像。

这有一些渲染的选项:

  • dagre-d3是一个基于d3的dagre渲染器
  • JointJS是一个渲染器,提供了在渲染后编辑图像的工具
  • Cytoscape.js是一个可以使用Dagre作为布局的完整的图像库,支持可视化和分析用例。 Cytoscape.js拥有复杂的渲染流程,由类似于CSS的样式表书写。

例子

首先,需要在HTML页面中导入Dagre库:

<script src="https://PATH/TO/dagre.min.js"></script>

在Node.js中:

var dagre = require("dagre");

使用graphlib在dagre中创建图像。此处,它的API值得一看

每个节点须是一个对象,且有如下属性:

  • width: node节点在像素上的宽度
  • height: node节点在像素上的高度

这些属性通常来自已确定节点所需空间的渲染引擎。

以下是一个快速制作节点和边的例子:

// 创建一个新的有向图
var g = new dagre.graphlib.Graph();

// 为图像标签设置一个空对象
g.setGraph({});

// 默认为每个边分配一个新的标签对象
g.setDefaultEdgeLabel(function() { return {}; });

// 新增图像的节点
// 第一个参数是节点的id
// 第二个参数是关于节点的元数据
// 在此样例中,我们将为每个节点添加label
g.setNode("kspacey",    { label: "Kevin Spacey",  width: 144, height: 100 });
g.setNode("swilliams",  { label: "Saul Williams", width: 160, height: 100 });
g.setNode("bpitt",      { label: "Brad Pitt",     width: 108, height: 100 });
g.setNode("hford",      { label: "Harrison Ford", width: 168, height: 100 });
g.setNode("lwilson",    { label: "Luke Wilson",   width: 144, height: 100 });
g.setNode("kbacon",     { label: "Kevin Bacon",   width: 121, height: 100 });

// 给图像添加边线
g.setEdge("kspacey",   "swilliams");
g.setEdge("swilliams", "kbacon");
g.setEdge("bpitt",     "kbacon");
g.setEdge("hford",     "lwilson");
g.setEdge("lwilson",   "kbacon");

下一步, dagre配置这些节点和边:

dagre.layout(g);

图标的布局信息将因配置而更新。节点将会获得以下属性:

  • x - 节点中心的x坐标
  • y - 节点中心的y坐标

边线获取的’顶点’属性, 其中包括边缘的控制点坐标,以及节点和线相交的点,假设为矩形:

  • x - 边线中, 此弯曲部分的中心的x坐标
  • y - 边线中, 此弯曲部分的中心的y坐标

为上述的对象生成以下布局:

g.nodes().forEach(v => console.log(`Node: ${v}: ${JSON.stringify(g.node(v))}`));

g.nodes().forEach(e => console.log(`Edge ${e.v} -> ${e.w} : ${JSON.stringify(g.edge(e))}`));

打印结果:

Node kspacey: {"label":"Kevin Spacey","width":144,"height":100,"x":80,"y":50}
Node swilliams: {"label":"Saul Williams","width":160,"height":100,"x":80,"y":200}
Node bpitt: {"label":"Brad Pitt","width":108,"height":100,"x":264,"y":200}
Node hford: {"label":"Harrison Ford","width":168,"height":100,"x":440,"y":50}
Node lwilson: {"label":"Luke Wilson","width":144,"height":100,"x":440,"y":200}
Node kbacon: {"label":"Kevin Bacon","width":121,"height":100,"x":264,"y":350}

Edge kspacey -> swilliams: {"points":[{"x":80,"y":100},{"x":80,"y":125},{"x":80,"y":150}]}
Edge swilliams -> kbacon: {"points":[{"x":80,"y":250},{"x":80,"y":275},{"x":203.5,"y":325.3396739130435}]}
Edge bpitt -> kbacon: {"points":[{"x":264,"y":250},{"x":264,"y":275},{"x":264,"y":300}]}
Edge hford -> lwilson: {"points":[{"x":440,"y":100},{"x":440,"y":125},{"x":440,"y":150}]}
Edge lwilson -> kbacon: {"points":[{"x":440,"y":250},{"x":440,"y":275},{"x":324.5,"y":324.21875}]}

配置布局

可以通过在图像中的适当对象上设置下表的属性,或在通过第二个参数来设置属性去配置图像的布局。 而通过参数设置优先性更高。

对象属性默认值描述
graphrankdirTB等级节点的方向。常见的有TB、BT、LR、RL。其中T是顶点(TOP), B是底部(Bottom), L是左边(Left),R是右边(Right)
graphalignundefined节点的对齐方式。有4个值: UL,UR,DL,DR。其中U是上(UP),D是下(down),L是左(left),R是右(Right)
graphnodesep50水平方向上, 分隔节点的距离(节点之间的间距)
graphedgesep10在水平方向上, 线段间的距离
graphranksep50每个层级间的距离
graphmarginx0图形左右边缘的距离
graphmarginy0图形上下边缘的距离
graphacyclicerundefined如果设置为贪婪模式(greedy), 则使用贪婪启发式来查找. 返回的弧设置是一组可以删除的线, 从而使图无环.
graphrankernetwork-simplex在输入的图像中, 为每个节点分配排名的算法类型. 可选值: network-simplex, tight-tree, longest-path
nodewidth0节点的宽度(像素)
nodeheight0节点的高度(像素)
edgeminlen1在线的开始和结束之间保持最少的长度
edgeweight1线的权重(宽度). 高权重的边通常比低权重的边更短更直
edgewidth0线的标签的宽度(像素)
edgeheight0线标签的高度(像素)
edgelabelposr根据线的位置来放置标签. l = left, c = center, r= right
edgelableoffset10标签和线段之间的距离. 仅当labelpos为l/r时生效

生成的图像

生成的图像将会有如下属性:

对象属性描述
graphheight整个图像的高度
graphwidth整个图像的宽度
node,edgex对节点来说,是节点中心的x坐标. 对边线来说, 是线段标签的x坐标
node,edgey对节点来说,是节点中心的y坐标. 对边线来说,是线段标签的y坐标
edgepoints由{x,y}组成的数组控制线段的控制点

第三部分例子

Darge已经被一些非常酷炫的项目所包含在内。 以下是一些比较突出的例子:

  • JointJS有一个插件是使用了dagre布局。这个项目聚焦在渲染和图表的交互, 这与Darge有很好的协同作用。如果你想以交互式的方式移动节点和控制边线, 这个项目很适合开始!

Jonathan Mace有一个简单的demo,可以交互式的浏览图表。 在这个demo中, 你可以突出显示路径,折叠子图,查看详细节点信息,以及更多!

  • nomnoml是一个在浏览器中绘制UML图表的工具。它使用带有dagre的自定义渲染器,在canvas中绘制图表。

  • Cytoscape.js是一个功能丰富的图论库, 并且支持Dagre作为布局。推荐阅读cytoscape-dagre

  • TensorBoard是一套用于检查和理解Tensorflow运行和图像的web程序。

推荐阅读

Darge采用了多部论文和著作的长处而成。如果你对dagre内部如何运行感兴趣, 这有些重要的文章推荐一读:

  • Dagre的大体骨架取自《Gansner, et al., “A Technique for Drawing Directed Graphs”》。这既为层绘图中涉及的各个阶段提供了高水平的概述, 也为深入研究中每个阶段的细节和问题提供了帮助。 除了基本的骨架, 我们专门利用此文章中所描绘的技术去制作一个非循环图, 且我们使用了网络单纯形算法(a graph theoretic specialization of the simplex algorithm, 单纯形算法的图论特化)进行排序. 如果要问哪篇文章适合开始学习分层图绘制, 那非这篇文献莫属。

  • 为了交叉最小化, 我们使用了这篇《Jünger and Mutzel, “2-Layer Straightline Crossing Minimization”》. 这篇文章提供了关于"各类启发式算法和交叉最小化精确算法"的对比。

  • 为了统计两层之间的边缘交叉数, 我们使用了O(|E| log |V_small|)算法。此算法的具体细节在此:《Barth, et al., “Simple and Efficient Bilayer Cross Counting”

  • 为了定位或者说是坐标分配, 我们从《Brandes and Köpf, “Fast and Simple Horizontal Coordinate Assignment”》提取算法。 当节点和边线的大小极大时,我们做了一些调整去获取更紧凑的图像。

  • 聚类图的实现极大地取材于Sander的《Layout of Compound Directed Graphs》。 这篇文章详细介绍了聚类图在布局所有阶段的影响, 还涵盖了许多相关问题。聚类图的交叉约减取自 Michael Forster的两篇论文: 《Applying Crossing Reduction Strategies to Layered Compound Graphs》、《A Fast and Simple Heuristic for Constrained Two-Level Crossing Reduction》