核心概念
节点
节点即画布中的一系列形状,可以是矩形,圆形,多边形等,我们可以根据业务需要自定义节点的形状。
内置节点
为了方便业务方的需求,更快的接入画布到业务中,我们提供了多种内置的节点,可以直接通过数据配置的方式直接接入。
基础节点
通用属性配置
// 所有节点通用属性
interface NodeData extends NodeConfig {
type: string; // 节点类型
id: string; // 节点的唯一标识
clientX?: number;
clientY?: number;
x?: number; // 节点位置的 x 值
y?: number; // 节点位置的 y 值
color: string; // 默认绘制的 hover, port高亮的值
fillColor: string; // 节点填充颜色
strokeColor: string; // 节点边的颜色
title: string; // 节点名称
outputs?: number[][]; // 出口节点位置
inputs?: number[][]; // 入口节点位置
width?: number; // 节点宽度
height?: number; // 节点高度
outPortFillColor: string; // port的填充色
portColor: string; // port默认颜色
baseNodeCfg: Partial<baseNodeCfg>; // baseNode属性
cardNodeCfg: Partial<cardNodeCfg>; // cardNode属性
[key: string]: any; // 可能存在一些自定义的属性值
}
基础节点配置
// base节点属性
interface baseNodeCfg {
type: 'block' | 'icon' | 'blockText';
status: 'notReady' | 'success' | 'inProgress' | 'failure' | 'stop' | 'lock' | 'special';
icon: string; // icon的类
blockTitle: string; //
subTitle: string;// 第二行的文案 title对应第一行的文案
statusIcon: string; // 状态icon
statusFillColor: string; // 状态颜色
blockFillColor: string; // 左侧块状填充色
description: string;
leftFillWidth: number;
leftIconColor: string;
statusDesc: string;
}
卡片节点
卡片节点配置
interface cardNodeCfg {
panels: object[] | string[]; // 下面展示文案
icon: string; // 头部icon
iconColor: string; // icon颜色
subTitle: string; // 右侧文案
color: string; // 文字颜色
}
如何使用 icon
icon 我们是使用的公司提供的 iconfont,具体的项目地址是iconfont.sankuai.com,具体的使用方式跟其他字体图标一致,直接使用 class 即可。
如何自定义节点
首先,我们需要绘制出节点的形状,以下面的节点为例,我们分步演示如何画出一个节点。
第一步:定义节点的关键形状。
function createNode (group, config, width, height) {
const { strokeColor, fillColor } = cfg;
// 外边框
const keyShape = group.addShape('rect', {
attrs: {
x: 0, // 相对坐标
y: 0, // 相对坐标
width: width, // 节点宽
height: height, // 节点高
stroke: strokeColor, // 外边框颜色
fill: fillColor, // 填充颜色
radius: 2 // 半径
}
});
return keyShape;
}
G6 中,每个节点都必须有一个关键形状,我们可以将其理解为节点的外部轮廓。我们通过group.addShape()
方法来定义关键形状,这里我们定义了矩形react
,也可以定义其他形状,然后在第二个参数中传入配置即可。
createNode
函数中的前两个参数group
与config
会在此函数执行的时候由 G6 传入相关配置,group
为 G6 的概念,代表一组图形,config
代表我们配置节点的参数,比如我们配置节点的时候这样配置{strokeColor: '#ff0000', fillColor: '#00ff00'}
,则渲染的时候就会渲染出外边框是红色,填充色为绿色的图形。
第二步:在 group 里定义左边底色
group.addShape('rect', {
attrs: {
x: 0,
y: 0,
width: h - 1.5,
height: h,
fill: strokeColor,
radius: [2, 0, 0, 2]
},
draggable: true
});
第三步,我们给节点加上文字描述,作为节点名称
// 文字
const textShape = group.addShape('text', {
attrs: {
x: (height - 14) / 2 + height,
y: 9,
width: width - height - (height - 14) / 2,
fill: 'rgba(0, 0, 0, 0.92)',
fontSize: 13,
textBaseline: 'top',
text: name
}
});
第四步,我们给节点加上一个图片标签,美观的同时也让其更有意义
// 增加左侧图片
const image =
'data:image/png;base64,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';
group.addShape('image', {
attrs: {
x: (height - 16) / 2,
y: (height - 16) / 2,
width: 16,
height: 16,
img: image
},
draggable: true
});
至此,我们就创建了一个节点,只要配置好数据,我们就能在画布上展示一系列这样的节点了。
port
节点与节点之间,如果要产生关系,需要通过连线来表示,要想将两个节点相连,需要通过 port 进行操作,所以一个节点需要分别有入线port
以及出线port
,否则其就是一个孤立的节点,不会与其他节点产生关系。
如何绘制 port
绘制 port 非常简单,只需要在节点数据中配置即可,我们通过下面的例子讲解:
上面的例子中,将鼠标移到节点上,你会发现上边有两个入线port
,下边有三个出线port
,那如何设置呢?其实很简单,只需要如下配置即可:
const config = {
type: 'rectNode',
id: 'node1', // String,该节点存在则必须,节点的唯一标识
x: 100, // Number,可选,节点位置的 x 值
y: 20, // Number,可选,节点位置的 y 值
color: '#1ea565',
fillColor: '#ffffffc0',
strokeColor: '#1ea565',
name: '节点1',
inputs: [[0, 0.5]], // 以左上角坐标为(0,0),右下角坐标为(1,1)
outputs: [
[1, 0],
[1, 0.5],
[1, 1],
],
}
可以看到,我们在component
对象里配置了两个数组,分别为inputs
与outputs
,每个数组项就是一个 port,这里只需要传入portId
以及name
即可,port
的位置会以节点边框的宽度进行平分,达到视觉上的美观。
边
上一节讲到,节点与之间的关系通过连线来表示,那如何配置连线呢?我们通过以下例子进行说明。
可以看到,节点 1 与节点 2 通过连线表明他们之间有某种关系,要实现连线,我们可以如下配置:
{
edges: [
{
source: "node4",
// String,必须,起始点 id
target: "node1",
// String,必须,目标点 id
sourceAnchorIndex: 0,
// 所在outputs的下标
targetAnchorIndex: 0,
// outputs的长度 + 所在inputs的下标
style: {
endArrow: {
path: "M 0,0 L 20,10 L 20,-10 Z",
d: 5,
fill: "#f00",
stroke: "#0f0",
opacity: 0.5,
lineWidth: 3
// ...
}
},
type: "cubic"
}
]
}
flow-graph-g6
内置的连线,我们只需要简单配置即可实现常规的业务需求。
内置连线
如何配置内置连线
线段通用配置
interface EdgeData
extends EdgeConfig {
type: string; // 边类型
source: string; // 起始节点 id
target: string; // 目标节点 id
sourceAnchorIndex?: number; // 起始点port索引
targetAnchorIndex?: number; // 目标点port索引
style?: EdgeStyle; // 线的样式
label?: string; // 线的文本
labelCfg: labelCfg; // 文本配置项
[key
:
string
]:
any; // 可能存在一些自定义的属性值
baseLineCfg?: Partial<baseLineCfg>; // 自定义线段配置
}
自定义线段配置
interface baseLineCfg {
type: 'rect' | 'rectText' | 'rectIcon' | 'icon' | 'dash' | 'statusText' | 'normal'; // 边类型
rectStrokeColor: string; // 矩形border颜色
rectFillColor: string; // 矩形填充色
rectRadius: number; // 默认为10 rect、rectText、rectIcon下生效
rectWidth: number; // 不建议使用
rectHeight: number; // 不建议使用
iconColor: string;
textColor: string;
icon: string; // icon的类
label: string; // 展示文案
showDashed: boolean; // 是否展示虚线
statusFillColor: string; // 状态颜色 type为statusText时生效
}
除了初始化配置,我们还可以手动将两个节点相连,现在您就可以用鼠标将节点 2 与节点 3 相连,动手体验感受更加深刻。
如何自定义边
除了内置的线段 line、Polyline、Quadratic、Cubic、Arc、Loop 之外,我们还可以自定义边,那如何进行边的自定义,我们通过以下例子进行说明
第一步:定义边的关键形状。
G6.registerEdge('hvh', {
draw (cfg, group) {
const startPoint = cfg.startPoint;
const endPoint = cfg.endPoint;
const shape = group.addShape('path', {
attrs: {
stroke: '#333',
path: [
['M', startPoint.x, startPoint.y],
['L', endPoint.x / 2 + (1 / 2) * startPoint.x, startPoint.y], // 三分之一处
['L', endPoint.x / 2 + (1 / 2) * startPoint.x, endPoint.y], // 三分之二处
['L', endPoint.x, endPoint.y],
],
},
// must be assigned in G6 3.3 and later versions. it can be any value you want
name: 'path-shape',
});
return shape;
},
});
第二步:指定边的类型。
{
edges: [
{
id: "edge1",
target: "node2",
source: "node1",
type: "hvh"
},
{
id: "edge2",
target: "node3",
source: "node1",
type: "hvh"
}
],
}
事件系统
与 flow-graph-g6 的交互过程中,所有数据都是通过事件传递的。flow-graph-g6 封装了 11 种事件,每种事件对应着不同的动作,详情见下表:
动作 | 事件 |
---|---|
拖动节点开始 | nodeDragStart |
拖动节点结束 | nodeDragEnd |
鼠标悬浮节点 | nodeHover |
鼠标从节点上移除 | nodeUnHover |
右键单击节点 | nodeRightClick |
选中节点(左键单击节点) | nodeSelect |
节点由选中态变为非选中态 | nodeUnselect |
鼠标悬浮 port | portHover |
创建连线 | edgeCreate |
左键单击连线 | edgeClick |
右键单击连线 | edgeRightClick |
鼠标悬浮连线 | edgeHover |
鼠标离开连线 | edgeUnHover |
点击画布 | canvasClick |
监听事件
flow-graph-g6
通过 graphUtil
导出所有事件的事件名,每一个Flow
实例都会维护一个自己的eventemitter3
实例,因此我们可以使用eventemitter3
的方法来绑定以及解绑事件。我们可以通过flow.bus
获取flow
实例的eventemitter3
实例,所以我们就可以通过flow.bus.on
方法监听事件,通过flow.bus.off
方法解绑事件。
我们通过给节点加一个选中事件的例子进行演示:
上面的例子中,用鼠标左键点击节点,就会弹出一个浏览器原生 alert 框,里面显示点击的节点名称。要配置这样的功能,核心代码只要以下几行:
import { graphUtil } from '@ss/mtdv-graph-flow';
const flow = new Flow({/*...*/ })
const { events } = graphUtil;
flow.bus.on(events.nodeSelect, e => {
alert(`您点击了${e.model.name}`);
});
插件机制
G6 中,如果想要改变节点或边的状态,一种方式是在注册节点的时候声明状态,然后在需要改变状态的地方调用graph.setItemState
方法。flow-graph-g6 中分别对节点和边进行了一些状态的声明,具体如下:
node:
状态 | 描述 |
---|---|
selected | 节点被选择后的状态 |
hover | 节点被 hover 的状态 |
highlight | 节点高亮态,用来区分正常节点 |
failHighlight | 另一种高亮态,颜色与 highlight 有所区分 |
portHighlight | port 高亮状态 |
default | 正常状态 |
edge:
状态 | 描述 |
---|---|
selected | 边被选中后的状态 |
hover | 边被 hover 后的状态 |
unHover | 边取消选中后的状态 |
highlight | 边高亮状态,用来区分正常节点 |
default | 正常状态 |
这些状态主要是改变节点或边的颜色,用来区分业务上不同的类型。我们可通过初始化节点的时候对节点的颜色进行配置;对于边的颜色,目前只支持通过注册复写的形式进行配置。
下面演示如何通过配置区分节点的状态展示:
如上面的例子所示,当我们用鼠标点击节点,会发现节点展示的状态并不一致,节点 1 展示偏绿色,节点 2 展示偏蓝色。
这里我们只需要在配置节点的时候声明不同的颜色即可。
{
nodes: [
// 节点1
{
// ...
color: '#1ea565',
// ...
},
// 节点2
{
// ...
color: '#1239C7',
// ...
}
]
}
但是有时候我们希望做到更加精细的配置,此时就可以通过插件的方式注册或重写状态,这样你就可以随心所欲地定制不同状态的展现形式了。