JavaScript is required

节点数据模型(JsonNode / RGNode

节点是 relation-graph 中最基础的数据单元。它既承担“业务实体”的角色,也承担布局、渲染、交互命中的基础载体。

实际开发中会遇到两种节点对象:

  • JsonNode:你传入图谱的数据对象,常见于 nodeschildrenaddNodeaddNodessetJsonData
  • RGNode:图谱运行时生成的节点对象,常见于 getNodeByIdgetNodes、事件回调、插槽参数、编辑器组件。

JsonNode 是输入格式,RGNode 是运行时格式。不要把运行时对象完整保存为业务数据;导出或持久化时应使用 getGraphJsonData()transRGNodeToJsonObject()

1. 最小可用节点

最小节点只需要 id

const node = {
  id: 'user-1'
};

实际项目中通常会同时设置 text

const node = {
  id: 'user-1',
  text: '张三'
};

字段规则:

  • id 必须唯一且稳定。图谱内部通过它建立节点索引、连线端点、展开折叠关系和更新定位。
  • text 是节点显示文本。relation-graph 使用 text,不是 label
  • 当前源码对历史数据有兼容:如果新增节点时没有 text 但存在 label,会把 label 当作 text 使用并输出警告;如果 text 也没有,则可能使用 id 作为文本。新代码不建议依赖这种兼容行为。

2. JsonNode 字段说明

标识与业务字段

字段 类型 默认值 说明
id string 必填 节点唯一标识。连线的 from/to、更新 API、查询 API 都依赖它。
text string '' 或兼容使用 label/id 节点文本。默认节点模板会显示它;自定义节点插槽也通常从这里读取标题。
type string '' 业务类型。可用于插槽模板分发,也会影响节点类型类名,例如按类型写 CSS。
data Record<string, any> {} 业务扩展数据。推荐把业务属性放在这里,不要塞进 relation-graph 的结构字段。
targetType string RGInnerConnectTargetType.Node 节点作为连接目标时的类型标识。普通节点通常不用设置;FakeLine 或连接编辑器扩展时才需要关注。

显示、展开与交互字段

字段 类型 默认值 说明
expanded boolean true 控制树形关系中该节点是否展开。折叠后,后代节点会在可见性计算中被隐藏。
hidden boolean false 主动隐藏节点。隐藏节点不会正常渲染,并会影响关联线的可见性计算。
selected boolean false 节点的“选中/多选”状态,常用于编辑器批量操作。和 checkedNodeId 这种单个 checked 状态不是同一概念。
disablePointEvent boolean 未设置时跟随 options.disableNodePointEvent 禁用该节点的鼠标/触摸事件命中。适合装饰性节点或希望点击穿透的场景。
disableDrag boolean false 禁止拖拽该节点。实际是否可拖还会受到全局 options.disableDragNode 影响。
expandHolderPosition `‘hide’ ‘left’ ‘top’
alwaysRender boolean 未设置 性能模式下的渲染提示。源码在可见项计算中会特殊处理它,使节点更倾向于保留渲染。普通业务节点通常不需要设置。

expandedhidden 的区别:

  • hidden 是节点自身隐藏。
  • expanded: false 是树关系中的折叠,会使其后代不可见。
  • 如果你直接批量修改节点的 hidden/expanded,必要时调用 updateNodesVisibleProperty() 让运行时可见性重新计算。

节点形状与外观字段

字段 类型 默认值 说明
nodeShape RGNodeShape options.defaultNodeShape,默认 RGNodeShape.rect 节点几何形状。影响默认节点外观、连线与节点的交点计算、缩略图/EasyView 绘制。
color string options.defaultNodeColor,默认 #ffffff 节点背景色。建议使用 CSS 颜色值。
borderColor string options.defaultNodeBorderColor,默认 #666666 节点边框颜色。
borderWidth number options.defaultNodeBorderWidth,默认 1 节点边框宽度,单位按像素理解。
borderRadius number options.defaultNodeBorderRadius,默认 4 节点圆角,主要影响矩形节点。
fontColor string CSS 默认变量 默认节点文本颜色。使用完全自定义节点插槽时,是否生效取决于你的插槽是否使用这些变量/字段。
fontSize number CSS 默认变量 默认节点文本字号。
opacity number 1 节点透明度。建议取值 01
className string '' 附加到节点 DOM 的类名。适合做主题级样式覆盖。
zIndex number 0 节点层级。用于控制节点之间的覆盖顺序。

RGNodeShape 可选值:

枚举 数值 说明
RGNodeShape.circle 0 圆形节点。连线交点按圆/椭圆边界计算,缩略图中按圆形绘制。
RGNodeShape.rect 1 矩形节点。默认值。连线交点按矩形边界或指定方向计算。

尺寸与坐标字段

字段 类型 默认值 说明
x number 0 节点左上角在画布坐标系中的 X 坐标。自动布局会改写它。
y number 0 节点左上角在画布坐标系中的 Y 坐标。自动布局会改写它。
width number options.defaultNodeWidth 或由 DOM 测量 节点逻辑宽度。设置后也会影响 el_W 初始值。
height number options.defaultNodeHeight 或由 DOM 测量 节点逻辑高度。设置后也会影响 el_H 初始值。
el_W number 运行时测量 节点实际渲染宽度。输入时可作为初始测量值,但通常由图谱根据 DOM 更新。
el_H number 运行时测量 节点实际渲染高度。输入时可作为初始测量值,但通常由图谱根据 DOM 更新。
fixed boolean false 固定节点坐标。布局附加处理其他分组时会跳过固定节点;力导向布局中也常用于控制节点不被自动移动。
force_weight number 未设置 力导向布局中的节点权重/质量类参数。值越高通常意味着节点在力学计算中更“重”,具体效果取决于当前布局实现。

坐标与尺寸要点:

  • x/y 是画布坐标,不是页面坐标。
  • width/height 更适合表达“你希望节点多大”。
  • el_W/el_H 是运行时测量值,很多布局和连线计算依赖它。
  • 如果使用复杂自定义节点插槽且不设置 width/height,布局通常需要等首轮渲染测量完成后再执行。

树结构输入字段

字段 类型 默认值 说明
children JsonNode[] 树形数据快捷写法。导入时会被展开成扁平节点与连线。

children 只适合输入阶段:

const data = {
  rootId: 'root',
  nodes: [
    {
      id: 'root',
      text: '根节点',
      children: [
        { id: 'child-1', text: '子节点 1' },
        { id: 'child-2', text: '子节点 2' }
      ]
    }
  ],
  lines: []
};

await graphInstance.setJsonData(data);

导入后,运行时会使用扁平的 nodeslines 和内部 lot 结构管理父子关系。不要在运行时直接修改 node.children 来期望图谱自动增删节点。

3. RGNode 运行时字段

RGNode 继承大部分 JsonNode 字段,并补充运行时计算信息。

字段 类型 说明
type string 运行时一定存在,未设置时为空字符串。
x / y number 运行时一定存在,未设置时为 0
nodeShape RGNodeShape 运行时一定存在,由节点自身或 defaultNodeShape 解析得到。
data Record<string, any> 运行时一定存在,未设置时为 {}
lot object 布局与树关系内部结构,包含父子节点、层级、排序、强度等信息。不要作为业务数据持久化。
rgChildrenSize number 当前节点的子节点数量/可展开规模相关运行时统计。
rgShouldRender boolean 性能模式或视口裁剪后的“是否应该渲染”判断。
rgCalcedVisibility boolean 综合 hidden、父级折叠、运行时计算后的可见性。

典型读取:

const node = graphInstance.getNodeById('user-1');

if (node?.rgCalcedVisibility) {
  console.log(node.x, node.y, node.el_W, node.el_H);
}

不建议直接依赖的字段:

  • lot:内部布局关系字段,结构可能随版本调整。
  • rgShouldRender:性能渲染策略结果,不等同于业务可见。
  • el_W/el_H:可读取用于布局/辅助线,但持久化时通常不需要保存。

4. 节点创建、查询、更新、删除

创建节点

graphInstance.addNode({
  id: 'n1',
  text: '节点 1'
});

graphInstance.addNodes([
  { id: 'n2', text: '节点 2' },
  { id: 'n3', text: '节点 3', x: 200, y: 80 }
]);

addNodes 会跳过已经存在的节点 id,不会用同 id 新对象覆盖旧节点。要修改旧节点,请使用 updateNode

查询节点

const node = graphInstance.getNodeById('n1');
const nodes = graphInstance.getNodes();
const checkedNode = graphInstance.getCheckedNode();
const selectedNodes = graphInstance.getSelectedNodes();

更新节点

graphInstance.updateNode('n1', {
  text: '节点 1(已更新)',
  color: '#dbeafe',
  borderColor: '#2563eb'
});

graphInstance.updateNodePosition('n1', 320, 160);

graphInstance.updateNodeData('n1', {
  owner: 'team-a',
  status: 'running'
});

更新规则:

  • updateNode(id, partial) 是浅合并字段。
  • 更新 data 时,如果只想合并业务字段,优先使用 updateNodeData
  • 修改位置时优先使用 updateNodePosition,力导向布局运行中它会同步布局器内部缓存。

删除节点

graphInstance.removeNodeById('n1');

graphInstance.removeNodesByIds(['n2', 'n3']);

const node = graphInstance.getNodeById('n4');
if (node) {
  graphInstance.removeNode(node);
}

删除节点会由数据提供者处理相关运行时数据。实际业务中建议在删除前自行确认关联线是否也符合你的业务预期。

5. 推荐数据写法

const nodes = [
  {
    id: 'service-api',
    text: 'API 服务',
    type: 'service',
    nodeShape: RGNodeShape.rect,
    color: '#eff6ff',
    borderColor: '#2563eb',
    borderWidth: 1,
    borderRadius: 8,
    width: 160,
    height: 56,
    data: {
      owner: '平台组',
      level: '核心系统'
    }
  },
  {
    id: 'cache',
    text: 'Redis',
    type: 'middleware',
    fixed: true,
    x: 360,
    y: 120,
    data: {
      cluster: 'cache-prod'
    }
  }
];

推荐原则:

  • id/text/type/data 表达业务实体。
  • color/borderColor/borderWidth/borderRadius/nodeShape 表达核心视觉语义。
  • className 做主题扩展,不要把所有视觉语义只写在 CSS 里。
  • width/height 稳定布局,尤其是自定义节点插槽。
  • fixed 区分手动坐标节点与自动布局节点。

6. 常见问题

为什么我的节点位置被改掉了?

调用 setJsonData()doLayout()appendJsonData(..., true) 时,布局器会重新计算节点位置。需要完全手动摆放时,使用 layoutName: 'fixed',或者避免在更新后自动重排。

为什么节点隐藏了,连线也不见了?

普通连线的可见性会参考起点/终点节点的 rgCalcedVisibility。如果任一端不可见,相关 RGLink 通常也不会渲染。

为什么自定义节点插槽样式和缩略图不一致?

缩略图/EasyView 依赖节点数据字段,例如 nodeShapecolorborderColorborderWidth。如果只在插槽内部 CSS 写背景和边框,缩略图无法知道这些语义。

selected 和 checked 有什么区别?

  • selected 是节点自身字段,适合多选和批量编辑。
  • checked 状态由 options.checkedNodeId / checkedItem 管理,通常表示当前焦点节点。

7. 下一步阅读