# nodeModel

LogicFlow中所有的节点都会有一个nodeModel与其对应。由于数据驱动视图的机制,我们对节点的所有操作事实上就是对model的操作。大多数情况下,我们不建议直接对nodeModel的属性进行赋值操作,而是调用model或者graphModel上提供的方法。

警告

在对LogicFlow内部源码不熟悉的情况,对model的属性进行赋值操作可能会引起很多不符合预期的问题。例如在model中x,y表示节点的位置,如果想要移动节点直接修改x,y的话,会出现节点被移动了,而节点上的文本、节点相连的边都没有动。所以想要移动节点,最好的方法还是调用graphModel上的moveNode方法来实现。

nodeModel上节点属性有很多,由于用途不一样,我们对其进行了分类。

# 数据属性

节点的数据属性是指LogicFlow图数据是用于标识节点的数据。在流程图保存时一般都只保存节点的数据属性。

名称 类型 是否必须 描述
id String 节点 id
type String 节点类型
x number 节点中心x轴坐标
y number 节点中心y轴坐标
text TextObject 节点文本
properties Object 节点业务自定义属性

TextObject

名称 类型 是否必须 描述
value String 文本内容
x number 文本中心x轴坐标
y number 文本中心y轴坐标
draggable boolean 文本是否允许被拖动调整位置,保存时不会保存此属性
editable boolean 文本是否允许被双击编辑,保存时不会保存此属性

# 状态属性

一般用于自定义节点的时候,基于状态属性进行更细粒度的样式显示。

名称 类型 是否必须 描述
isSelected boolean 节点是否被选中
isHovered boolean 节点是否在hover状态
isHitable boolean 节点是否可点击
draggable boolean 节点是否可拖动
isShowAnchor boolean 是否显示锚点
visible boolean 是否显示, 1.1.0新增

# 形状属性

LogicFlow的形状属性主要是控制基础节点的主要外观。形状属性可以通过setAttributes或者initNodeData来设置。具体设置方式见自定义节点的形状属性

名称 类型 是否必须 描述
width number 节点的宽度
height number 高度的高度
radius number 矩形节点特有,节点的圆角
r number 圆形节点特有,圆的半径。对于圆形节点,会自动基于半径计算出节点的高度和宽度
rx number 椭圆节点和菱形节点存在,水平圆角的半径。会自动基于半径计算出节点的宽度
ry number 椭圆节点和菱形节点存在,垂直圆角的半径。会自动基于半径计算出节点的高度
points [number,number][] 多边形节点特有,多边形顶点。会自定基于顶点计算出节点的宽度和高度

# 其它属性

LogicFlow在model上还维护一些属性,开发者可以通过这些属性拿到一些信息。例如拿到graphModel, 节点的基础model类型等。

名称 类型 是否必须 描述
graphModel object 整个画布对应的model,详情见
zIndex number 节点在z轴的高度,元素重合时,zIndex高的在上面, 默认为1
state number 元素状态,不同的状态对应着元素显示效果。DEFAULT = 1 默认显示;TEXT_EDIT = 2 此元素正在进行文本编辑;ALLOW_CONNECT = 4, 此元素允许作为当前边的目标节点;NOT_ALLOW_CONNECT = 5, 此元素不允许作为当前边的目标节点
BaseType string 当前model的基础类型,对于节点,则固定为node。主要用在节点和边混合的时候识别此model是节点还是边。
modelType string 当前model的类型,可取值有node, rect-node,circle-node,polygon-node,ellipse-node,diamond-node, html-node,text-node
moveRules array 节点被移动之前的校验规则
sourceRules array 节点连接其它节点时的校验规则
targetRules array 节点被其它节点连接时的校验规则
autoToFront boolean 控制节点选中时是否自动置顶,默认为true.
incoming object 进入当前节点的所有边和节点,v1.1.4
outgoing object 离开当前节点的所有边和节点, v1.1.4
virtual boolean - 是否为虚拟节点,默认false。当为true时导出数据不会包含此元素。 v1.1.24

modelType与type的区别是什么?

在自定义节点的时候,type可以是开发者自定义的任何值,但是在LogicFlow内部,涉及到这个节点的计算时,我们需要感知到这个节点的具体形状,这个时候不能用type, 而是要用modelType来判断。

# 样式属性

LogicFlow所有的节点最终都是以SVG DOM的方式渲染。但是除了形状属性之外,所有的其他属于svg的属性都不会直接存在nodeModel。当开发者想要对SVG DOM添加更多的svg属性 (opens new window)时,可以通过重写nodeModel上获取节点样式属性方法来实现。

# getNodeStyle

支持重写,自定义节点样式属性. 默认为主题 baseNode

class UserTaskModel extends RectNodeModel {
  getNodeStyle() {
    const style = super.getNodeStyle();
    style.stroke = 'blue';
    style.strokeDasharray = '3 3';
    return style;
  }
}

# getTextStyle

支持重写,自定义节点文本样式属性,默认为主题 nodeText

class UserTaskModel extends RectNodeModel {
  getTextStyle() {
    const style = super.getTextStyle();
    style.fontSize = 16;
    return style;
  }
}

# getAnchorStyle

支持重写,自定义节点锚点样式属性,默认为主题 anchor

class UserTaskModel extends RectNodeModel {
  getAnchorStyle(anchorInfo) {
    const style = super.getAnchorStyle(anchorInfo);
    style.stroke = "rgb(24, 125, 255)";
    style.r = 3;
    style.hover.r = 8;
    style.hover.fill = "rgb(24, 125, 255)";
    style.hover.stroke = "rgb(24, 125, 255)";
    return style;
  }
}

# getAnchorLineStyle

支持重写,自定义节点锚点拖出连接线的样式属性,默认为主题 anchorline

class UserTaskModel extends RectNodeModel {
  getAnchorLineStyle(anchorInfo) {
    const style = super.getAnchorLineStyle();
    style.stroke = "rgb(24, 125, 255)";
    return style;
  }
}

# getOutlineStyle

支持重写,自定义节点轮廓框的样式属性,默认为主题 outline

class UserTaskModel extends RectNodeModel {
  getOutlineStyle() {
    const style = super.getOutlineStyle();
    style.stroke = "red";
    style.hover.stroke = "red";
    return style;
  }
}

# initNodeData

支持重写,初始化节点数据,将传入的图数据(data)转换为节点属性, 所以需要调用super.initNodeData触发转换方法。

  • super.initNodeData之前,对图数据进行处理。
  • super.initNodeData之后,对节点属性进行初始化。
class UserTaskModel extends RectResize.model {
  initNodeData(data) {
    // 可以在super之前,强制设置节点文本位置不居中,而且在节点下面
    if (!data.text || typeof data.text === 'string') {
      data.text = {
        value: data.text || "",
        x: data.x,
        y: data.y + 40,
      };
    }
    super.initNodeData(data);
    this.width = 100;
    this.height = 80;
  }
}

提示

initNodeData和setAttributes都可以对nodeModel的属性进行赋值,但是两者的区别在于:

  • initNodeData只在节点初始化的时候调用,用于初始化节点的属性。
  • setAttributes除了初始化调用外,还会在properties发生变化了调用。

以上面代码为例,由于节点缩放的时候,会更新properties中的缩放后的大小,也就会触发setAttributes。如果在setAttributes中定义节点的初始大小的话,会导致节点无法缩放。

# setAttributes

设置model形状属性,每次properties发生变化会触发

class UserTaskModel extends RectNodeModel {
  setAttributes() {
    const size = this.properties.scale || 1;
    this.width = 100 * size
    this.height = 80 * size
  }
}

# createId

支持重写,自定义节点id的生成规则.

注意

  1. 请保证此方法返回id的唯一性。
  2. 此方法为同步方法,如果想要异步修改节点id, 请参考#272 (opens new window)
import { v4 as uuidv4 } from 'uuid';

class UserTaskModel extends RectNodeModel {
  createId() {
    return uuidv4()
  }
}

# getData

获取被保存时返回的数据。LogicFlow有固定节点数据格式。如果期望在保存数据上添加数据,请添加到properties上。

不支持重写此方法

const nodeModel = lf.getNodeModelById('node_1');
const nodeData = nodeModel.getData();

# getProperties

获取节点属性

不支持重写此方法

const nodeModel = lf.getNodeModelById('node_1');
const properties = nodeModel.getProperties();

# getDefaultAnchor

重新设置默认锚点, 可以给锚点加上id等自定义属性,用于对锚点的验证。

class cNode extend RectNodeModel {
  // 定义节点只有左右两个锚点. 锚点位置通过中心点和宽度算出来。
  getDefaultAnchor() {
    const { width, height, x, y, id } = this;
    return [
      {
        x: x - width / 2,
        y,
        name: 'left',
        id: `${id}_0`
      },
      {
        x: x + width / 2,
        y,
        name: 'right',
        id: `${id}_1`,
        edgeAddable: false
      },
    ]
  }
}

锚点属性

名称 类型 是否必须 描述
x number 锚点x坐标
y number 锚点y坐标
id string 锚点id
edgeAddable boolean 是否允许此锚点手动创建连线,默认为true

# getConnectedSourceRules

获取当前节点作为边的起始节点规则。

支持重写,重写的时候,可以自定义添加额外规则。所有的规则中,有任一规则不满足,则禁止连线。

class EndNodeModel extends CircleNodeModel {
  getConnectedSourceRules(): ConnectRule[] {
    const rules = super.getConnectedSourceRules();
    const geteWayOnlyAsTarget = {
      message: '结束节点只能连入,不能连出!',
      validate: (source: BaseNodeModel, target: BaseNodeModel, sourceAnchor, targetAnchor) => {
        let isValid = true;
        if (source) {
          isValid = false;
        }
        return isValid;
      },
    };
    rules.push(geteWayOnlyAsTarget);
    return rules;
  }
}

# getConnectedTargetRules

获取当前节点作为边的目标节点规则。

支持重写,重写的时候,可以自定义添加额外规则。所有的规则中,有任一规则不满足,则禁止连线。

class StartEventModel extends CircleNodeModel {
  getConnectedTargetRules() {
    const rules = super.getConnectedTargetRules();
    const notAsTarget = {
      message: '起始节点不能作为边的终点',
      validate: () => false,
    };
    rules.push(notAsTarget);
    return rules;
  }
}

# updateText

修改节点文本内容

参数

名称 类型 必传 默认值 描述
value string true 文本值
const nodeModel = lf.getNodeModelById('node_1');
nodeModel.updateText('hello world');

# setZIndex

设置节点zIndex

const nodeModel = lf.getNodeModelById('node_1');
nodeModel.setZIndex(999);

# setProperties

设置节点properties

lf.on("node:click", ({ data }) => {
  lf.getNodeModelById(data.id).setProperties({
    disabled: !data.properties.disabled,
    scale: 2
  });
});

# deleteProperty

删除节点的某个属性

lf.on("node:click", ({ data }) => {
  lf.getNodeModelById(data.id).deleteProperty('disabled');
  lf.getNodeModelById(data.id).deleteProperty('scale');
});