Skip to content

layout · 几何 ​

把 BoundDocument 变成盒子、端口落点、路由与标签落点。全库只有这一段产生最终坐标。

导出 ​

measureDocument、placeDocument、attachEndpoints、routeEdges、layoutDocument, 以及内置引擎、路由和相关类型。

签名 ​

ts
function measureDocument(bound: BoundDocument, options: MeasureOptions): Result<Measured>;
function placeDocument(bound: BoundDocument, measured: Measured, options?: PlaceOptions): Result<Placement>;
function placeDocumentAsync(bound: BoundDocument, measured: Measured, options?: PlaceOptions): Promise<Result<Placement>>;
function attachEndpoints(bound: BoundDocument, placement: Placement, options?: AttachOptions): Result<Attached>;
function routeEdges(bound: BoundDocument, attached: Attached, options?: RouteOptions): Result<LayoutResult>;

function layoutDocument(
  input: DrawDocument | BoundDocument,
  options: LayoutOptions,
): Result<LayoutResult>;
function layoutDocumentAsync(
  input: DrawDocument | BoundDocument,
  options: LayoutOptions,
): Promise<Result<LayoutResult>>;

传入原始文档时,layoutDocument 会先调用 bindDocument;传入 BoundDocument 时复用已有结论。

四段 ​

measure ​

产出 Measured:

  • 每个节点的 Size;
  • 容器标题带高度;
  • 节点与边标签的折行结果和尺寸。

标签的 maxWidth / overflow 在这里完成,build 只画已经量过的行。

place ​

把 Measured 交给 LayoutEngine。内置:

引擎适合什么
layered有方向关系的图,默认引擎
grid网格铺开
explicitpins 已给出位置

v2 引擎实现 layout(input): PlaceOutput | Promise<PlaceOutput>,输入是树形 PlaceNode[],可回传 ports 与 routes。同步入口遇到 Promise 返回 ENGINE_ASYNC; Pipeline 使用 runAsync,layout 使用 layoutDocumentAsync。

旧引擎仍可直接传入,或用 fromV1Engine(engine) 适配。

attach ​

把 port 声明变成 Attached.ports[portKey]:

ts
interface PortPlacement {
  point: Point;
  side: Side;
}
  • fixed:side 与 offset 固定;
  • side:side 固定,同侧槽位自动分配;
  • free:先按对端方向选 side,再分配槽位。

同侧自动端口按对端位置排序,最小间距默认 12px;空间不足时发出 PORT_CROWDED。 Attached.anchors 是 v1 兼容视图,内容与 ports.point 相同。

route ​

给每条边产出 Route,并计算 LayoutResult.labels。

ts
interface Route {
  start: Point;
  end: Point;
  bends: Point[];
  routing?: "orthogonal" | "straight" | "spline";
}

边标签优先放在最长折段中点;label.position 可以覆盖为路径比例。无法避开节点时发出 LABEL_COLLISION 警告。

LayoutResult ​

ts
interface LayoutResult {
  boxes: Record<string, Rect>;
  anchors: Record<string, Point>;
  routes: Record<string, Route>;
  labels: Record<string, LabelPlacement>;
  /** 内容紧包围盒 */
  extents: Rect;
  /** 文档显式画布 */
  camera?: Rect;
  diagnostics: Diagnostic[];
}

注入点 ​

  • LayoutEngine:决定盒子位置;
  • Router:决定折点;
  • TextMeasurer:决定文字尺寸;
  • LayoutOptions.registry:让原始文档在入口处完成 bind。

未注册类型的回落已经在 bind 完成,layout 不再重复发 UNKNOWN_*。

MIT License