从0到1实现流程图04-连线篇

开始

连线是 X6 中非常重要的一部分,X6 内置了很多实用的连线功能,也提供了优雅的扩展机制 ,这是相比于其他流程图框架占据绝对优势的地方。本文通过实现流程图的连线功能来一步步介绍 X6 的连线机制。

实现

图形定义

X6 中连线分两种形式,代码生成的和用户手动拖拽而成,首先来看怎么通过代码建立连线:

// source 或 target 是坐标点
graph.addEdge({
  source: [0, 0],
  target: [100, 100]
})


// source 或 target 是节点对象
graph.addEdge({
  source: sourceNode,
  target: targetNode,
})

// source 或 target 是节点 ID
graph.addEdge({
  source: 'sourceId',
  target: 'targetId',
})

// source 或 target 是连接桩
graph.addEdge({
  source: { cell: 'cellId1', port: 'portId1' },
  target: { cell: 'cellId2', port: 'portId2' }
})

如果想通过手动操作来创建连线,需要有两个条件:

  1. 需要从具有 magnet: true 属性的元素上才能手动拖拽出连线
  2. 需要在全局 connecting 配置中自定义 createEdge 方法
import { Graph, Shape } from '@antv/x6'

const graph = new Graph({
  connecting: {
    createEdge() {
      return new Shape.Edge()
    },
  },
})
graph.addNode({
  shape: 'rect',
  x: 100,
  y: 100,
  width: 80,
  height: 40,
  attrs: {
    body: {
      stroke: 'red',
      magnet: true
    }
  }
})
graph.addNode({
  shape: 'rect',
  x: 400,
  y: 100,
  width: 80,
  height: 40,
  attrs: {
    body: {
      stroke: 'red',
      magnet: true
    }
  }
})
1.gif

默认的连线样式并不好看,我们经常需要自己来定义连线的样式,其实连线和图形都是由 markup 和 attrs 来定义的,默认连线的 markup 为:

[
  {
    tagName: 'path',
    selector: 'wrap',
    groupSelector: 'lines',
    attrs: {
      fill: 'none',
      cursor: 'pointer',
      stroke: 'transparent',
      strokeLinecap: 'round',
    },
  },
  {
    tagName: 'path',
    selector: 'line',
    groupSelector: 'lines',
    attrs: {
      fill: 'none',
      pointerEvents: 'none',
    },
  },
]

其中 line 为实际展示的连线,wrap 是为了方便响应交互的占位元素。一般场景我们不需要去自定义连线的 markup,但是我们经常需要配置 attrs 来定制连线样式:

graph.addEdge({
  source: 'sourceId',
  target: 'targetId',
  attrs: {
    line: {
      stroke: '#000',  // 连线颜色
      strokeWidth: 1,  // 连线宽度
    },
  },
})
2.png

连线的箭头也是非常容易配置,比如我们想将上面箭头修改为实心箭头,并且显示的修长一点儿:

graph.addEdge({
  source: 'sourceId',
  target: 'targetId',
  attrs: {
    line: {
      stroke: '#000',
      strokeWidth: 1,
      targetMarker: {
        name: 'block',
        width: 12,
        height: 8,
      }
    },
  },
})
3.png

和节点类似,动态修改连线的属性方式如下:

const edge = graph.addEdge({
  source: 'sourceId',
  target: 'targetId',
  attrs: {
    line: {
      stroke: '#000',
      strokeWidth: 1,
    },
  },
})

edge.attr('line/stroke', '#ccc')

同样,连线也提供了注册自定义连线的方式来解决重复定义问题:

Graph.registerEdge('custom-edge', {
  inherit: 'edge',
  attrs: {
    line: {
      strokeWidth: 1,
      stroke: '#5755a1',
      targetMarker: {
        name: 'path',
        d: 'M5.5,15.499,15.8,21.447,15.8,15.846,25.5,21.447,25.5,9.552,15.8,15.152,15.8,9.552z',
      }
    },
  },
})

graph.addEdge({
  shape: 'custom-edge',
  source: [50, 50],
  target: [300, 50],
})

graph.addEdge({
  shape: 'custom-edge',
  source: [50, 150],
  target: [300, 150],
  attrs: {
    line: {
      stroke: '#31d0c6'
    }
  }
})
4.png

路由和连接器

在每一种图场景中,连线形态有所不同,比如流程图和思维导图的连线样式:


5.png
6.png

流程图的连线是横平竖直的,思维导图的连线是一种树状,X6 提供了路由和连接器两个概念来实现不同形态的连线。路由就是在原有连线基础上增加一些固定点,让连线符合某种规则,比如 orth 路由,增加固定点后,边的每一条线段都是水平或垂直的正交线段。连接器就是将连线所有点经过一定规则加工后,产生一定形状的连线,比如 smooth 连接器,是用三次贝塞尔曲线线连接起点、路由点和终点。

在我们的流程图中,需要横平竖直的连线,并且能避开重合的图形,所以选择 manhattan 路由,然后连线的拐角处需要平滑处理,这里选择 rounded 连接器。路由和连接器都可以在 connecting 配置中全局配置(对所有连线有效),也可以在一条连线中单独配置:

// 全局配置
const graph = new Graph({
  connecting: {
    router: 'manhattan',
    connector: {
      name: 'rounded',
      args: {
        radius: 8,
      }
    }
  }
})

// 单独针对一条边配置
graph.addEdge({
  source: 'sourceId',
  target: 'targetId',
  router: 'manhattan',
  connector: {
    name: 'rounded',
    args: {
      radius: 8,
    }
  }
})
7.gif

起点和终点

连线的起点和终点是由 NodeAnchorConnectionPoint 共同确定。

  1. 起点:从第一个路径点或目标节点的中心(没有路径点时)画一条参考线到源节点的锚点,然后根据 connectionPoint 指定的交点计算方法,计算参考线与图形的交点,该交点就是边的起点。
  2. 终点:从最后一个路径点或源节点的中心(没有路径点时)画一条参考线到目标节点的锚点,然后根据 connectionPoint 指定的交点计算方法,计算参考线与图形的交点,该交点就是边的终点。

上面的描述可能比较难以理解,可以看下面的例子,图形 1 和 图形 2 的 NodeAnchor 默认在图形中心,ConnectionPoint 默认是 boundary,也就是图形边框,从锚点 1 拉出一条线来连接到锚点 2,这条线与图形边框的交点就是连线的起点和终点。


8.png

经常会遇到这种情况,起点和终点在连接桩的中心,那么 NodeAnchor 和 ConnectionPoint 该怎么设置呢?


9.png
const graph = new Graph({
  // 锚点在连接桩的中心,连接点是锚点本身
  connecting: {
    anchor: 'center',
    connectionPoint: 'anchor',
  }
})

工具

工具是渲染在节点/边上的小部件,用于增强节点/边的交互能力,现在我们需要在连线上增加一个线段工具,在边的每条线段的中心渲染一个工具条,可以拖动工具条调整线段两端的路径点的位置。

graph.addEdge({
  tools: [
    {
      name: 'segments',
      args: {
        attrs: {
          fill: '#459CDB',
        }
      }
    }
  ]
})
10.gif

最后

连线是 X6 的核心功能之一,通过本文可以了解到连线的基础用法,我们可以完成大部分场景下连线的配置,在一些复杂场景下,还需要在连线上定制标签的需求,可以参考 edge-label

  1. 源码:传送门
  2. 记得给 X6 仓库加星
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容