logicflow 基础操作

1,429 阅读15分钟

logicflow 基础操作

一、 register(): 注册图标方法

1、节点modelview

model: 数据层,包含节点各种样式(边框、颜色)、形状(宽高、顶点位置)、业务属性等。

view: 视图层,控制节点的最终渲染效果,通过改变model就可以满足自定义节点,同时可以在view 上定制更加复杂的svg元素。

LogicFlow基于MVVM模式实现的,在自定义一个节点的时候,我们可以重新定义节点的modelview ,通过重写定义在model上获取样式相关的方法和重写view上的getShape来定义复杂的节点外观。

这是一个基于继承内置节点并重写model的自定义节点例子👇,节点自定义采用了不同的方式实现😊。

1.1 自定义注册图标的源码如下:
  /**
   * 注册元素(节点 or 边)
   * @param config 注册元素的配置项
   * @private
   */
  private registerElement(config: RegisterConfig) {
    let ViewComp = config.view
​
    if (config.isObserverView !== false && !ViewComp.isObserved) {
      ViewComp.isObserved = true
      ViewComp = observer(ViewComp)
    }
​
    this.setView(config.type, ViewComp)
    this.graphModel.setModel(config.type, config.model)
  }

注册图形:根据源码注册的自定义图形需要有三个参数:

params:{type,view,model}

const registerElements = (lf: LogicFlow) => {
  const elements = [
    combine,
    square,
    circleStart
  ]
​
  map(elements, (customElement) => {
    lf.register(customElement)
  })
}

说明:每个扩展的节点形状格式

例如square:

import { BaseNodeModel, h, RectNode, RectNodeModel } from '@logicflow/core'export class SquareModel extends RectNodeModel {
  setAttributes() {
    const size = 80
    const circleOnlyAsTarget = {
      message: '正方形节点下一个节点只能是圆形节点',
      validate: (source?: BaseNodeModel, target?: BaseNodeModel | any) => {
        return target?.type === 'circle' // 确认上面 target 类型定义
      }
    }
​
    this.width = size
    this.height = size
    this.anchorsOffset = [
      [size / 2, 0],
      [-size / 2, 0]
    ]
    this.sourceRules.push(circleOnlyAsTarget)
  }
}
​
export class SquareView extends RectNode {
  getTextStyle() {
    const { model } = this.props
​
    const style = model.getTextStyle()
    const {
      model: { properties = {} }
    } = this.props
    if (properties.isUsed) {
      style.color = 'red'
    }
    return style
  }
​
  // getShape 的返回值是一个通过 h 方法创建的 svg 元素
  getShape() {
    const { x, y, width, height } = this.props.model
    const { fill, stroke, strokeWidth } = this.props.model.getNodeStyle()
    const attrs = {
      x: x - width / 2,
      y: y - height / 2,
      width,
      height,
      stroke,
      fill,
      strokeWidth
    }
    // 使用 h 方法创建一个矩形
    return h('g', {}, [
      h('rect', { ...attrs }),
      h(
        'svg',
        {
          x: x - width / 2 + 5,
          y: y - height / 2 + 5,
          width: 25,
          height: 25,
          viewBox: '0 0 1274 1024'
        },
        h('path', {
          fill: stroke,
          d: 'M655.807326 287.35973m-223.989415 0a218.879 218.879 0 1 0 447.978829 0 218.879 218.879 0 1 0-447.978829 0ZM1039.955839 895.482975c-0.490184-212.177424-172.287821-384.030443-384.148513-384.030443-211.862739 0-383.660376 171.85302-384.15056 384.030443L1039.955839 895.482975z'
        })
      )
    ])
  }
}
​
export default {
  type: 'square',
  view: SquareView,
  model: SquareModel
}
​

例如combine:

import { h, BaseNode, BaseNodeModel } from '@logicflow/core'
​
export class CombineNode extends BaseNode {
  getShape() {
    const { x, y } = this.props.model
    const { fill } = this.props.model.getNodeStyle()
    return h(
      'g',
      {
        transform: `matrix(1 0 0 1 ${x - 25} ${y - 25})`
      },
      h('path', {
        d: 'm  0,6.65 l  0,36.885245901639344 c  1.639344262295082,8.196721311475411 47.540983606557376,8.196721311475411  49.18032786885246,0 l  0,-36.885245901639344 c -1.639344262295082,-8.196721311475411 -47.540983606557376,-8.196721311475411 -49.18032786885246,0c  1.639344262295082,8.196721311475411 47.540983606557376,8.196721311475411  49.18032786885246,0 m  -49.18032786885246,5.737704918032787c  1.639344262295082,8.196721311475411 47.540983606557376,8.196721311475411 49.18032786885246,0m  -49.18032786885246,5.737704918032787c  1.639344262295082,8.196721311475411 47.540983606557376,8.196721311475411  49.18032786885246,0',
        fill: fill,
        strokeWidth: 2,
        stroke: 'red',
        fillOpacity: 0.95
      })
    )
  }
}
​
export class CombineModel extends BaseNodeModel {
  setAttributes() {
    this.width = 50
    this.height = 60
    this.fill = 'orange'
​
    this.anchorsOffset = [
      [0, -this.height / 2],
      [this.width / 2, 0],
      [0, this.height / 2],
      [-this.width / 2, 0]
    ]
  }
}
​
export default {
  type: 'combine',
  view: CombineNode,
  model: CombineModel
}
​

例如circleStart:

import { h, CircleNode, CircleNodeModel } from '@logicflow/core'export class StartNode extends CircleNode {
  getLabelShape() {
    const { model } = this.props
    const {
      x,
      y
    } = model
    return h(
      'text',
      {
        fill: '#000000',
        fontSize: 12,
        x: x - 12,
        y: y + 4,
        width: 50,
        height: 25
      },
      'Start'
    )
  }
  getShape() {
    const { model } = this.props
    const {
      x,
      y,
      r,
    } = model
    const {
      fill,
      stroke,
      strokeWidth } = model.getNodeStyle()
    return h(
      'g',
      {
      },
      [
        h(
          'circle',
          {
            cx: x,
            cy: y,
            r,
            fill,
            stroke,
            strokeWidth
          }
        ),
        this.getLabelShape()
      ]
    )
  }
}
export class StartModel extends CircleNodeModel {
  // 自定义节点形状属性
  initNodeData(data) {
    data.text = {
      value: (data.text && data.text.value) || '',
      x: data.x,
      y: data.y + 35,
      dragable: false,
      editable: true
    }
    super.initNodeData(data)
    this.r = 20
  }
  // 自定义节点样式属性
  getNodeStyle() {
    const style = super.getNodeStyle()
    return style
  }
  // 自定义锚点样式
  getAnchorStyle() {
    const style = super.getAnchorStyle();
    style.hover.r = 8;
    style.hover.fill = "rgb(24, 125, 255)";
    style.hover.stroke = "rgb(24, 125, 255)";
    return style;
  }
  // 自定义节点outline
  getOutlineStyle() {
    const style = super.getOutlineStyle();
    style.stroke = '#88f'
    return style
  }
  getConnectedTargetRules() {
    const rules = super.getConnectedTargetRules()
    const notAsTarget = {
      message: '起始节点不能作为连线的终点',
      validate: () => false
    }
    rules.push(notAsTarget)
    return rules
  }
}
​
export default {
  type: "circleStart",
  view: StartNode,
  model: StartModel
}
1.2 默认注册的图标有10个,7个node,3个edge

源码如下:

  private defaultRegister() {
    // LogicFlow default Nodes and Edges
    const defaultElements: RegisterConfig[] = [
      // Node
      {
        type: 'rect',
        view: _View.RectNode,
        model: _Model.RectNodeModel,
      },
      {
        type: 'circle',
        view: _View.CircleNode,
        model: _Model.CircleNodeModel,
      },
      {
        type: 'polygon',
        view: _View.PolygonNode,
        model: _Model.PolygonNodeModel,
      },
      {
        type: 'text',
        view: _View.TextNode,
        model: _Model.TextNodeModel,
      },
      {
        type: 'ellipse',
        view: _View.EllipseNode,
        model: _Model.EllipseNodeModel,
      },
      {
        type: 'diamond',
        view: _View.DiamondNode,
        model: _Model.DiamondNodeModel,
      },
      {
        type: 'html',
        view: _View.HtmlNode,
        model: _Model.HtmlNodeModel,
      },
      // Edge
      {
        type: 'line',
        view: _View.LineEdge,
        model: _Model.LineEdgeModel,
      },
      {
        type: 'polyline',
        view: _View.PolylineEdge,
        model: _Model.PolylineEdgeModel,
      },
      {
        type: 'bezier',
        view: _View.BezierEdge,
        model: _Model.BezierEdgeModel,
      },
    ]
    this.batchRegister(defaultElements)
  }

如图所示:

二、图标的事件注册

1、on:注册事件;emit:触发事件;off:注销事件
   const lf = new LogicFlow({
        ...this.config,
        container: this.$refs.container,
      })
      //注册事件
       this.lf.on('node:click', ({data}) => {
        console.log('node:click', data)
      })
      //触发事件
      this.lf.emit('node:click', (data) => {
        console.log(data)
      })
      this.lf.off('node:click')

三、图标的渲染

1、render(data)

data的数据类型:{Nodes :[],Edges :[]}

Nodes (节点):

每个节点表示图中的一个元素,比如开始节点、结束节点、用户自定义节点等。

  • id: 每个节点的唯一标识符,用于区分不同的节点。

  • type: 节点的类型。不同类型的节点具有不同的图形和功能。

  • x: 节点在画布上的 x 坐标。

  • y: 节点在画布上的 y 坐标。

  • text

    : 节点显示的文本信息,包括以下字段:

    • x: 文本相对于节点的 x 坐标。
    • y: 文本相对于节点的 y 坐标。
    • value: 显示的文本内容,比如节点名称或描述。
  • properties: 节点的自定义属性,通常用于保存特定业务逻辑的数据。在这里为空 {}

  • baseType: 节点的基本类型,通常为 node,表明这是一个普通的节点。

Edges (连线)

连线用于连接节点,定义节点之间的流向。

  • id: 每条连线的唯一标识符。
  • type: 连线的类型,polyline 表示折线。
  • sourceNodeId: 连线的起始节点 ID。
  • targetNodeId: 连线的目标节点 ID。
  • startPoint: 连线的起始点坐标(x, y)。
  • endPoint: 连线的结束点坐标(x, y)。
  • properties: 连线的自定义属性,也通常为空 {}
  • pointsList: 连线的中间点列表,用于定义连线的路径,由一系列坐标点(x, y)构成。
  • text (可选): 连线中显示的文本,通常用于决策节点的分支连线。

源代码:

 export interface GraphConfigData {
    nodes?: NodeConfig[]
    edges?: EdgeConfig[]
  }  
​
 // 表示边缘连接线
  export interface EdgeConfig<P extends PropertiesType = PropertiesType> {
    id?: string
    type?: string // 连接节点的线类型
​
    sourceNodeId: string // 连接开始节点的id
    sourceAnchorId?: string
    targetNodeId: string // 连接结束节点的id
    targetAnchorId?: string
    startPoint?: Point // 线的开始的位置 {x,y}
    endPoint?: Point // 线的结束的位置 {x,y}
    text?: TextConfig | string  // 线的内容 {"x": 850,"y": 400,"value": "N"}
    pointsList?: Point[]
    zIndex?: number
    properties?: P // 线的自定义属性
  }
  
  // 节点的属性
   export interface NodeConfig<P extends PropertiesType = PropertiesType> {
    id?: string
    type: string //节点类型名字
    x: number // x轴的位置
    y: number // y轴的位置
    text?: TextConfig | string // 节点内的文字内容
    zIndex?: number
    properties?: P // 节点的自定义属性
    virtual?: boolean // 是否虚拟节点
    rotate?: number
​
    rotatable?: boolean // 节点是否可旋转
    resizable?: boolean // 节点是否可缩放
​
    [key: string]: any
  }
​
​
​
* @param graphData 图数据
   */
  render(graphData: GraphConfigData) {
    let graphRawData = cloneDeep(graphData)
    if (this.adapterIn) {
      graphRawData = this.adapterIn(graphRawData)
    }
    this.renderRawData(graphRawData)
  }
​

例子数据:

{
  "nodes": [
    {
      "id": "742356ea-762b-4899-b96a-bd567e3c4361",
      "type": "start",
      "x": 220,
      "y": 170,
      "text": {
        "x": 350,
        "y": 190,
        "value": "sdfasf"
      },
      "properties": {},
      "baseType": "node"
    },
    {
      "id": "dacda6b6-48d3-4dff-911d-287704eb23d8",
      "type": "rect",
      "x": 350,
      "y": 170,
      "properties": {},
      "baseType": "node",
      "text": {
        "x": 350,
        "y": 170,
        "value": "基础节点"
      }
    },
    {
      "id": "49106603-2b88-4b2c-b1e8-723c1f2210bd",
      "type": "user",
      "x": 530,
      "y": 170,
      "properties": {},
      "baseType": "node",
      "text": {
        "x": 530,
        "y": 220,
        "value": "自定义节点"
      }
    },
    {
      "id": "647fa2bc-98ee-40cf-99c5-4756c0bc130d",
      "type": "push",
      "x": 690,
      "y": 170,
      "properties": {},
      "baseType": "node",
      "text": {
        "x": 690,
        "y": 220,
        "value": "自定义节点 可添加下一个节点/节点组"
      }
    },
    {
      "id": "37e7bac3-8804-4237-abe9-7b6065c207e9",
      "type": "download",
      "x": 690,
      "y": 320,
      "properties": {},
      "baseType": "node"
    },
    {
      "id": "6bb4396f-54c9-4b1c-b34c-87ef004f2e29",
      "type": "user",
      "x": 840,
      "y": 320,
      "properties": {},
      "baseType": "node"
    },
    {
      "id": "abf76937-63b8-493c-a978-a4a58bc4f6b8",
      "type": "push",
      "x": 840,
      "y": 470,
      "properties": {},
      "baseType": "node"
    },
    {
      "id": "b119f24f-2669-4a90-a837-afd853b2ffcc",
      "type": "end",
      "x": 990,
      "y": 320,
      "properties": {},
      "baseType": "node"
    },
    {
      "id": "60326ad9-cae2-4a85-ae98-d340fb7bd67f",
      "type": "end",
      "x": 990,
      "y": 470,
      "properties": {},
      "baseType": "node"
    }
  ],
  "edges": [
    {
      "id": "00f55245-513e-43a2-9cb0-adb61b01adc8",
      "type": "polyline",
      "sourceNodeId": "742356ea-762b-4899-b96a-bd567e3c4361",
      "targetNodeId": "dacda6b6-48d3-4dff-911d-287704eb23d8",
      "startPoint": {
        "x": 240,
        "y": 170
      },
      "endPoint": {
        "x": 300,
        "y": 170
      },
      "properties": {},
      "pointsList": [
        {
          "x": 240,
          "y": 170
        },
        {
          "x": 300,
          "y": 170
        }
      ]
    },
    {
      "id": "bbf9754f-603e-48e4-85fe-84ed44459a6a",
      "type": "polyline",
      "sourceNodeId": "dacda6b6-48d3-4dff-911d-287704eb23d8",
      "targetNodeId": "49106603-2b88-4b2c-b1e8-723c1f2210bd",
      "startPoint": {
        "x": 400,
        "y": 170
      },
      "endPoint": {
        "x": 495,
        "y": 170
      },
      "properties": {},
      "pointsList": [
        {
          "x": 400,
          "y": 170
        },
        {
          "x": 495,
          "y": 170
        }
      ]
    },
    {
      "id": "12bb443b-4070-4a08-ad4d-2755ee856f0d",
      "type": "polyline",
      "sourceNodeId": "49106603-2b88-4b2c-b1e8-723c1f2210bd",
      "targetNodeId": "647fa2bc-98ee-40cf-99c5-4756c0bc130d",
      "startPoint": {
        "x": 565,
        "y": 170
      },
      "endPoint": {
        "x": 655,
        "y": 170
      },
      "properties": {},
      "pointsList": [
        {
          "x": 565,
          "y": 170
        },
        {
          "x": 655,
          "y": 170
        }
      ]
    },
    {
      "id": "33fa3c09-9c29-4cb7-8373-67d537b8b623",
      "type": "polyline",
      "sourceNodeId": "647fa2bc-98ee-40cf-99c5-4756c0bc130d",
      "targetNodeId": "37e7bac3-8804-4237-abe9-7b6065c207e9",
      "startPoint": {
        "x": 690,
        "y": 205
      },
      "endPoint": {
        "x": 690,
        "y": 295
      },
      "properties": {},
      "pointsList": [
        {
          "x": 690,
          "y": 205
        },
        {
          "x": 690,
          "y": 295
        }
      ]
    },
    {
      "id": "2b5a5e89-005e-4fda-9a44-dc795050534f",
      "type": "polyline",
      "sourceNodeId": "37e7bac3-8804-4237-abe9-7b6065c207e9",
      "targetNodeId": "6bb4396f-54c9-4b1c-b34c-87ef004f2e29",
      "startPoint": {
        "x": 715,
        "y": 320
      },
      "endPoint": {
        "x": 805,
        "y": 320
      },
      "properties": {},
      "pointsList": [
        {
          "x": 715,
          "y": 320
        },
        {
          "x": 805,
          "y": 320
        }
      ]
    },
    {
      "id": "62b54f8a-bcfd-494b-9144-5aeb09ca77a1",
      "type": "polyline",
      "sourceNodeId": "6bb4396f-54c9-4b1c-b34c-87ef004f2e29",
      "targetNodeId": "b119f24f-2669-4a90-a837-afd853b2ffcc",
      "startPoint": {
        "x": 875,
        "y": 320
      },
      "endPoint": {
        "x": 970,
        "y": 320
      },
      "properties": {},
      "text": {
        "x": 920,
        "y": 310,
        "value": "Y"
      },
      "pointsList": [
        {
          "x": 875,
          "y": 320
        },
        {
          "x": 970,
          "y": 320
        }
      ]
    },
    {
      "id": "ba816d4a-5785-4911-9f78-03933f1463a1",
      "type": "polyline",
      "sourceNodeId": "6bb4396f-54c9-4b1c-b34c-87ef004f2e29",
      "targetNodeId": "abf76937-63b8-493c-a978-a4a58bc4f6b8",
      "startPoint": {
        "x": 840,
        "y": 355
      },
      "endPoint": {
        "x": 840,
        "y": 435
      },
      "properties": {},
      "text": {
        "x": 850,
        "y": 400,
        "value": "N"
      },
      "pointsList": [
        {
          "x": 840,
          "y": 355
        },
        {
          "x": 840,
          "y": 435
        }
      ]
    },
    {
      "id": "2b3007ed-7a13-4db7-a1ea-6691d7564c34",
      "type": "polyline",
      "sourceNodeId": "abf76937-63b8-493c-a978-a4a58bc4f6b8",
      "targetNodeId": "60326ad9-cae2-4a85-ae98-d340fb7bd67f",
      "startPoint": {
        "x": 875,
        "y": 470
      },
      "endPoint": {
        "x": 970,
        "y": 470
      },
      "properties": {},
      "pointsList": [
        {
          "x": 875,
          "y": 470
        },
        {
          "x": 970,
          "y": 470
        }
      ]
    }
  ]
}

四、设置主题 :

LogicFlow 提供了设置主题的方法,便于用户统一设置其内部所有元素的样式。 设置方式有两种:

  • 初始化LogicFlow时作为配置传入
  • 初始化后,调用LogicFlow的 setTheme 方法
  • 主题案例地址
方法一:
// 方法1:new LogicFlow时作为配置传入
const config = {
  domId: 'app',
  width: 1000,
  height: 800,
  style: { // 设置默认主题样式
    rect: { ... }, // 矩形样式
    circle: { ... }, // 圆形样式
    nodeText: { ... }, // 节点文本样式
    edgeText: { ... }, // 边文本样式
    anchor: { ... }, // 锚点样式
    // ...,
  },
}
const lf = new LogicFlow(config)

方法二:

// 方法2: 调用LogicFlow的setTheme方法
lf.setTheme({ // 设置默认主题样式
  rect: {...}, // 矩形样式
  circle: {...}, // 圆形样式
  nodeText: {...}, // 节点文本样式
  edgeText: {...}, // 边文本样式
  anchor: {...}, // 锚点样式
  ...
})

源代码的类型:只列出大概的

 export interface Theme {
    baseNode: CommonTheme // 所有节点的通用主题设置
    baseEdge: EdgeTheme // 所有边的通用主题设置

    /**
     * 基础图形节点相关主题
     */
    rect: RectTheme // 矩形样式
    circle: CircleTheme // 圆形样式
    diamond: PolygonTheme // 菱形样式
    ellipse: EllipseTheme // 椭圆样式
    polygon: PolygonTheme // 多边形样式

    /**
     * 基础图形线相关主题
     */
    line: EdgeTheme // 直线样式
    polyline: EdgePolylineTheme // 折现样式
    bezier: EdgeBezierTheme // 贝塞尔曲线样式
    anchorLine: AnchorLineTheme // 从锚点拉出的边的样式

    /**
     * 文本内容相关主题
     */
    text: TextNodeTheme // 文本节点样式
    nodeText: NodeTextTheme // 节点文本样式
    edgeText: EdgeTextTheme // 边文本样式
    inputText?: CommonTheme

    /**
     * 其他元素相关主题
     */
    anchor: AnchorTheme // 锚点样式
    arrow: ArrowTheme // 边上箭头的样式
    snapline: EdgeTheme // 对齐线样式
    rotateControl: CommonTheme // 节点旋转控制点样式
    resizeControl: CommonTheme // 节点旋转控制点样式
    resizeOutline: CommonTheme // 节点调整大小时的外框样式

    /**
     * REMIND: 当开启了跳转边的起点和终点(adjustEdgeStartAndEnd:true)后
     * 边的两端会出现调整按钮
     * 边连段的调整点样式
     */
    edgeAdjust: CircleTheme
    outline: OutlineTheme // 节点选择状态下外侧的选框样式
    edgeAnimation: EdgeAnimation // 边动画样式
  }

五、网格

网格是指渲染/移动节点的最小单位。网格最主要的作用是在移动节点的时候,保证每个节点中心点的位置都是在网格上。这样更有利于节点直接的对齐。一般来说,网格的间隔越大,在编辑流程图的时候,节点就更好对齐;网格的间隔越小,拖动节点的感觉就更加流畅。

网格默认关闭,渲染/移动最小单位为 1px,若开启网格,则网格默认大小为 20px,渲染节点时表示以 20 为最小单位对齐到网络,移动节点时表示每次移动最小距离为 20px。

注意

在设置节点坐标时会按照网格的大小来对坐标进行转换,如设置中心点位置{ x: 124, y: 138 } 的节点渲染到画布后的实际位置为 { x: 120, y: 140 }。所以使用 LogicFlow 替换项目中旧的流程设计器时,需要对历史数据的坐标进行处理。 在实际开发中,如果期望节点既可以中心对齐,也可以按照两边对齐。那么自定义节点的宽高需要是 grid 的偶数倍。也就是假设 grid 为 20,那么所有的节点宽度最好是 20、40、80、120 这种偶数倍的宽度。

开启网格

在创建画布的时候通过配置 grid 来设置网格属性

开启网格并应用默认属性:

const lf1 = new LogicFlow({  grid: true,})
// 等同于默认属性如下const lf2 = new LogicFlow({  grid: {    size: 20,    visible: true,    type: 'dot',    config: {      color: '#ababab',      thickness: 1,    },  },})

设置网格属性

支持设置网格大小、类型、网格线颜色和宽度等属性。

export type GridOptions = {

  size?: number  // 设置网格大小

  visible?: boolean,  // 设置是否可见,若设置为false则不显示网格线但是仍然保留size栅格的效果

  type?: 'dot' | 'mesh', // 设置网格类型,目前支持 dot 点状和 mesh 线状两种

  config?: {

    color: string,  // 设置网格的颜色

    thickness?: number,  // 设置网格线的宽度

  }

};

示例

去 CodeSandbox 查看示例

六、背景 Background

提供可以修改画布背景的方法,包括背景颜色或背景图片,背景层位于画布的最底层。

创建画布时,通过 background 选项来设置画布的背景层样式,支持透传任何样式属性到背景层。默认值为 false 表示没有背景。

const lf = new LogicFlow({  background: false | BackgroundConfig,})
type BackgroundConfig = {  backgroundImage?: string,  backgroundColor?: string,  backgroundRepeat?: string,  backgroundPosition?: string,  backgroundSize?: string,  backgroundOpacity?: number,  filter?: string, // 滤镜  [key: any]: any,};
const lf = new LogicFlow({

  // ...

  background: {

    backgroundImage: "url(../asserts/img/grid.svg)",

    backgroundRepeat: "repeat",

  },

});

示例

去 CodeSandbox 查看示例

七、节点的验证

在某些时候,我们可能需要控制边的连接方式,比如开始节点不能被其它节点连接、结束节点不能连接其他节点、用户节点后面必须是判断节点等,要想达到这种效果,我们需要为节点设置以下两个属性。

  • sourceRules - 当节点作为边的起始节点(source)时的校验规则
  • targetRules - 当节点作为边的目标节点(target)时的校验规则

以正方形(square)为例,在边时我们希望它的下一节点只能是圆形节点(circle),那么我们应该给square 添加作为source节点的校验规则。

写法一:

import { RectNode, RectNodeModel } from '@logicflow/core'
class SquareModel extends RectNodeModel {  initNodeData(data) {    super.initNodeData(data)
    const circleOnlyAsTarget = {      message: '正方形节点下一个节点只能是圆形节点',      validate: (sourceNode, targetNode, sourceAnchor, targetAnchor) => {        return targetNode.type === 'circle'      },    }    this.sourceRules.push(circleOnlyAsTarget)  }}

写法二:getConnectedSourceRules()

import LogicFlow, { PolygonNodeModel, PolygonNode } from '@logicflow/core';

class CustomHexagonModel extends PolygonNodeModel {
  getConnectedSourceRules() {
    const rules = super.getConnectedSourceRules();
    const geteWayOnlyAsTarget = {
      message: '下一个节点只能是circle',
      validate: (
        source: any,
        target: any,
        sourceAnchor: any,
        targetAnchor: any,
      ) => {
        console.log('sourceAnchor, targetAnchor', sourceAnchor, targetAnchor);
        return target.type === 'circle';
      },
    };
    rules.push(geteWayOnlyAsTarget);
    return rules;
  }
}

export default {
  type: 'hexagonNode',
  model: CustomHexagonModel,
  view: PolygonNode,
};