Skip to content

端口与锚点 ​

端口是文档里声明的“可连接位置”,锚点是布局算出来的“具体坐标”。 前者回答“能不能连”,后者回答“连到哪个像素”。

端口先声明,边再引用 ​

ts
{
  id: "service",
  type: "component",
  ports: [
    { id: "api", side: "right", constraint: "side" },
  ],
}
ts
{
  source: { node: "web" },
  target: { node: "service", port: "api" },
}

如果边引用了一个没有声明的端口,parseDocument 会报 UNKNOWN_PORT,布局不会猜一个位置。

默认锚点 ​

形状没有提供 anchors 时,端口按 side 和 offset 落在节点盒子上:

side点的位置
top(x + width × offset, y)
right(x + width, y + height × offset)
bottom(x + width × offset, y + height)
left(x, y + height × offset)

offset 可以是 0 到 1 的数字,也可以是 "25%" 这样的百分比字符串。对普通矩形来说, 这通常已经够用。

端口约束与同侧槽位 ​

constraint行为
fixedside 和 offset 都固定;缺省值,兼容 v1
sideside 固定,offset 自动分配
free根据对端方向选 side,再自动分配槽位

attachEndpoints 会把同一节点同一侧的自动端口集中排序,按最小间距 12px 等距分配。 边的书写顺序不会改变结果;空间不足时压缩并发出 PORT_CROWDED 警告。

自定义锚点 ​

圆盘、星形、头像这类形状,盒子的边缘不一定就是图形的真实表面。此时在注册项里实现 anchors:

ts
anchors(port, _props, box) {
  if (port.id === "center") {
    return { x: box.x + box.width / 2, y: box.y + box.height / 2 };
  }
  return defaultAnchor(port, box);
},

边和端口装饰都读取同一份 ctx.anchors。所以只要锚点改对,端口圆环和线端点会一起移动, 不会出现“看起来在端口上,实际连到别处”的情况。

没有指定端口时 ​

边没有写 port 时,布局会在两端盒子的边框上选一个朝对方的点。这个点不是形状表面上的 任意点,而是盒子的边框点;要精确控制位置,就声明端口。

当两个节点左右相邻、两端的高度范围又有交集时,路由可以直接走一条直线。只有在无法避免时 才会折一次,原因见布局与路由。

常见误解 ​

  • 端口不是装饰:画了一个小圆环,不会自动产生 anchor。
  • 默认是 fixed:想让库自动排槽位,必须显式写 side 或 free。
  • 端口不是全局 id:同一个端口名可以在多个节点上重复,边引用时必须带节点 id。
  • anchors 不是布局:它只返回点,不能改变节点盒子大小。
  • hidePorts 只关掉装饰:锚点仍然存在,边仍然可以准确连接。

MIT License