「AntV X6」从0到1实现客户旅程时光轴组件03-节点篇

716 阅读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实现客户旅程时光轴组件03-节点篇》文章正文。

节点

节点里面的最基础的元素——接下来我们从节点定义节点样式两个方面讲述在AntV X6中节点的使用:

  • 节点定义节点定义.png
  • 节点样式节点的视觉通道.png

节点定义

首先来看下一个简单的矩形节点的基础配置:

// 一个简单的矩形节点的基础配置
graph.addNode({
  shape: 'rect', // shape:定义节点的形状,X6 内置了 rect、circle、ellipse、polygon、polyline、image、html 等基础形状
  x: 100, // x/y:定义节点的左上角坐标
  y: 100,
  width: 80, // width/height:定义节点的尺寸
  height: 40,
  attrs: { // attrs: 可以将 attrs 看做 css 样式集合
    body: {
      stroke: 'red'
    }
  }
});
  • shape:定义节点的形状,X6 内置了 rectcircleellipsepolygonpolylineimagehtml 等基础形状;
  • x/y:定义节点的左上角坐标;
  • width/height:定义节点的尺寸 ;
  • attrs:看到 attrs 大家可能比较奇怪,这是什么东西?其实可以将 attrs 看做 css 样式集合,其中 body 类似于 css 选择器,body 的值是被选中元素的属性。那 body 又是哪来的呢?这里就要说的另一个重要的配置项markupmarkup 表示的是节点的 DOM 结构,内置的 rect 的默认 markup 为:
[
  {
    tagName: 'rect',
    selector: 'body',
  },
  {
    tagName: 'text',
    selector: 'label',
  },
]

渲染完成后,实际生效的 DOM 为:

<g data-cell-id="ca715562-8faf-4c88-a242-2b18d4ce47a6" data-shape="rect" class="x6-cell x6-node" transform="translate(100,100)">
  <rect fill="#ffffff" stroke="red" stroke-width="2" width="80" height="40"></rect>
  <text font-size="14" fill="#000000" text-anchor="middle" text-vertical-anchor="middle" font-family="Arial, helvetica, sans-serif" transform="matrix(1,0,0,1,40,20)"></text>
</g>

所以说一个节点是由 markupattrs 来决定结构和样式,我们可以通过设置 markupattrs 来定义自己业务中的节点,看下面的例子:

graph.addNode({
  shape: 'rect',
  x: 200,
  y: 80,
  width: 70,
  height: 70,
  markup: [
    {
      tagName: 'rect',
      selector: 'r1'
    },
    {
      tagName: 'circle',
      selector: 'c1'
    },
    {
      tagName: 'circle',
      selector: 'c2'
    },
    {
      tagName: 'circle',
      selector: 'c3'
    },
    {
      tagName: 'circle',
      selector: 'c4'
    }
  ],
  attrs: {
    r1: {
      width: 70,
      height: 70,
      stroke: '#ccc',
      rx: 12,
      ry: 12,
    },
    c1: {
      r: 10,
      cx: 20,
      cy: 20,
      fill: '#000'
    },
    c2: {
      r: 10,
      cx: 50,
      cy: 20,
      fill: '#000'
    },
    c3: {
      r: 10,
      cx: 20,
      cy: 50,
      fill: '#000'
    },
    c4: {
      r: 10,
      cx: 50,
      cy: 50,
      fill: '#000'
    },
  }
})

上面可以看到定义节点的时候,属性是固定写死的,在业务场景中,经常需要动态修改节点的样式,X6 中也提供了非常便利的方法:

const node = graph.addNode({
	shape: 'rect',
  x: 290,
  y: 100,
  width: 80,
  height: 40,
  attrs: {
    body: {
      stroke: 'red'
    }
  }
})
node.attr('body/stroke', 'green')
node.attr('body/fill', 'yellow')

那么问题来了,如果多个节点的结构和样式相似度很高,每次定义节点都要写很多类似的代码,有没有一种方式可以将节点之间的公共属性抽象出来呢?X6 提供了很优雅的方式来解决这个问题,首先注册自定义的节点类型,在这里配置公共的属性,然后在添加节点的时候指定 shape 值为刚才注册的节点类型。

Graph.registerNode('custom-rect', {
  inherit: 'rect', // 继承自 Shape.Rect
  width: 300, // 默认宽度
  height: 40, // 默认高度
  attrs: {
    body: {
      rx: 10, // 圆角矩形
      ry: 10,
      strokeWidth: 1,
      fill: '#5755a1',
      stroke: '#5755a1',
    },
    label: {
      fill: '#fff',
      fontSize: 18,
      refX: 10, // x 轴偏移,类似 css 中的 margin-left
      textAnchor: 'left', // 左对齐
    }
  },
})

graph.addNode({
  shape: 'custom-rect',
  x: 100,
  y: 200,
  width: 100,
  height: 50,
  label: 'rect1'
})
graph.addNode({
  shape: 'custom-rect',
  x: 250,
  y: 200,
  width: 100,
  height: 50,
  label: 'rect2',
  attrs: {
    body: {
      fill: '#ccc'
    }
  }
})

节点样式

节点做进一步的拆解,适用于表达节点的视觉样式的有大小颜色描边形状图标角标 这么几个视觉参数:

节点的视觉通道.png

  • 大小:通过width/height来定义节点的尺寸;
  • 颜色:通过attrs中的fill来定义填充颜色;
  • 描边:通过attrs中的stroke来定义描边颜色;
  • 形状:通过shape来定义节点形状,X6 内置了 rectcircleellipsepolygonpolylineimagehtml 等基础形状,另外也支持ReactVue组件;
  • 图标:同上;
  • 角标:节点右上角的圆形徽标。

另外,X6 不仅支持上文提到的基础的 SVG 节点,还具备在节点中渲染 React、Vue 组件的能力。在实际业务场景中,如果对 SVG 不熟悉或者节点内容复杂,我们可以根据技术栈选择 React/Vue 渲染,这样在节点内部,我们可以用熟悉的方式绘制各种复杂的内容。

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

参考资料