「AntV X6」从0到1实现客户旅程时光轴组件05-布局篇

1,477 阅读6分钟

我前一段时间写过一篇文章《「AntV」怎样用SVG & X6制作客户旅程时光轴》,分享了怎样通过使用SVG和X6制作客户旅程时光轴,得到了很多伙伴们的喜欢。

一些小伙伴找我要到了演示Demo的源代码,可是即使在有演示Demo源代码,在这基础之上再进行二次开发时却遇到了很多障碍。

软件/工具是知识和经验凝结的产物,在开发上遇到的很多障碍、往往是相关知识、开发经验或者能力方面有欠缺,所以我打算在演示Demo源代码基础之上,通过接下来的《「AntV X6」从0到1实现客户旅程时光轴组件》一系列文章,将我使用SVG和X6的相关知识和经验对大家进行分享,希望能帮到有同样需求的朋友。

《「AntV X6」从0到1实现客户旅程时光轴组件》会以系列文章的形式,有步骤、有重点地分享我使用AntV X6进行客户旅程时光轴组件实现相关的知识和经验,目前该系列文章会有如下6篇:

  1. 「AntV X6」从0到1实现客户旅程时光轴组件01-先导篇
  2. 「AntV X6」从0到1实现客户旅程时光轴组件02-画布篇
  3. 「AntV X6」从0到1实现客户旅程时光轴组件03-节点篇
  4. 「AntV X6」从0到1实现客户旅程时光轴组件04-连线篇
  5. 「AntV X6」从0到1实现客户旅程时光轴组件05-布局篇
  6. 「AntV X6」从0到1实现客户旅程时光轴组件06-动画篇

系列文章将会以“项目驱动”的方式进行技术知识和开发经验的分享,贯穿整个系列文章的客户旅程时光轴Demo如下:

回顾之前的文章,我们知道了一个客户旅程时光轴图由以下5个核心要素组成——

5个核心要素.png

  1. 点(节点,Node):旅程图中那些一个个的圆圈,被称为“节点”;
  2. 边(连线,Edge):两个节点中的连线,被称为“”;
  3. 标签(Label):节点下的说明文字,被称为“标签”;
  4. 布局(Layout):各个节点位置坐标的排列,被称为“布局”;
  5. 动画(Animation):在旅程时光轴图中,有一个从第一个节点一直到最后一个节点的描边动画

以下是《「AntV X6」从0到1实现客户旅程时光轴组件05-布局篇》文章正文。

布局

AntV X6提供了一个@antv/layout包——里面提供了包括grid布局、dagre布局、force布局等等布局算法供我们使用——我们往往会通过使用各个布局算法,将布局的结果作为我们节点的位置坐标。

在一篇名称为《可视化图布局算法浅析》的文章中总结了图可视化场景下常用的布局算法——

  • 几何布局:grid(网格布局算法),circle(环形布局算法),concentric(同心圆布局算法),radial(辐射状布局算法),avsdf(邻接点最小度优先算法,Adjacent Vertex with Smallest Degree First);

  • 层级布局:dagre(有向无环图树布局算法,Directed Acyclic Graph and Trees),breadthfirst(广度优先布局算法),elk(Eclipse布局算法,Eclipse Layout Kernel),klay(K层布局算法,K Lay);

  • 力导布局:fcose(最快复合弹簧内置布局算法,Fast Compound Spring Embedder),cola(约束布局,Constraint-based Layout),cise(环形弹簧内置布局算法,Circular Spring Embedder),elk2(Eclipse布局算法,Eclipse Layout Kernel),euler(欧拉布局算法),spread(扩展布局算法),fruchterman(Fruchterman-Reingold布局算法),combo(混合布局算法);

  • 其他布局:mds(高维数据降维布局算法,Multi Dimensional Scaling),random(随机布局算法)。

在当前的客户旅程时光轴Demo中,我们是结合了Dagre布局网格布局进行布局实现的——先使用Dagre算法进行一次布局计算,再使用网格布局处理一次。

Dagre布局

Dagre布局算法是“层次布局”的一个成熟算法实现,X6的@antv/layout布局包中就有Dagre布局的实现。

在 Dagre算法中定义了几个基本概念:

(1)rankDir:图的延展方向,分为由上到下(tb)、由下到上(bt)、由左到右(lr)、由右到左(rl)四种。

randir-lr-vs-tb.png

(2)rank:沿着图的延展方向划分的层级,每个顶点都存在于某个层级上,一个层级上可能有多个顶点。

rank.png

(3)level:在每个 rank 中针对每一个节点划分的级。不同 rank 中的 level 互不影响。

rank-level.png

关于Dagre布局更详细的内容,我写过一篇文章《Dagre算法简介以及在流程图自动布局中的应用》,感兴趣的可以去看看。

Dagre布局的使用很简单,实现如下——

const dagreLayout = new DagreLayout({
    type: 'dagre',
    rankdir: 'LR',
    // align: 'UR', // 居中对齐
    ranksep: 36,
    nodesep: 20,
  });
  dagreLayout.updateCfg({
    begin: begin,
    ranker: 'longest-path', // 'tight-tree' 'longest-path' 'network-simplex'
  });
  let dagreModel = dagreLayout.layout(data as any);
  graph.fromJSON(dagreModel);

经过Dagre布局之后,我们能得到从左往右的布局的一个旅程图,效果如下——

但是项目上,我们有一个需求是一行展示固定个数(比如一行6个),超出则换行显示(比如这里的客户旅程A和C)——

这时候我们需要在Dagre算法基础之上,再使用网格布局处理一次。

网格布局

网格布局是一种几何布局,我们可以通过把旅程节点划分到各个行和列中,然后根据节点所在的行和列、计算出节点实际所处的坐标。

在客户旅程项目中,跟正常网格布局稍微不一样的地方是,这里的旅程节点需要折行显示——

在这里我们做了如下处理:

  1. 对于奇数行,节点y坐标相同,x坐标值是节点的列号(columnNumber)进行计算;
  2. 对于偶数行,节点y坐标相同,x坐标值需要在上述步骤1的基础之上进行位置兑换。

在接下来的系列文章中,我们继续从“节点”、“连线”、“标签”、“布局”、“动画”这5个要素出发,通过结合下面的客户旅程时光轴图Demo案例,进行更详细的分解和讲述,希望能帮助到有需要的朋友:

参考资料