diff --git a/packages/plugins/free-auto-layout-plugin/src/layout/constant.ts b/packages/plugins/free-auto-layout-plugin/src/layout/constant.ts index 6e616239..2badca0e 100644 --- a/packages/plugins/free-auto-layout-plugin/src/layout/constant.ts +++ b/packages/plugins/free-auto-layout-plugin/src/layout/constant.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MIT */ -import { LayoutConfig } from './type'; +import { LayoutConfig, LayoutOptions } from './type'; export const DefaultLayoutConfig: LayoutConfig = { rankdir: 'LR', @@ -16,3 +16,8 @@ export const DefaultLayoutConfig: LayoutConfig = { acyclicer: undefined, ranker: 'network-simplex', }; + +export const DefaultLayoutOptions: LayoutOptions = { + getFollowNode: undefined, + enableAnimation: false, +}; diff --git a/packages/plugins/free-auto-layout-plugin/src/layout/layout.ts b/packages/plugins/free-auto-layout-plugin/src/layout/layout.ts index fe82bf3f..d3606112 100644 --- a/packages/plugins/free-auto-layout-plugin/src/layout/layout.ts +++ b/packages/plugins/free-auto-layout-plugin/src/layout/layout.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MIT */ -import { GetFollowNode, LayoutConfig, LayoutOptions, LayoutParams } from './type'; +import { LayoutConfig, LayoutOptions, LayoutParams } from './type'; import { LayoutStore } from './store'; import { LayoutPosition } from './position'; import { DagreLayout } from './dagre'; @@ -21,9 +21,8 @@ export class Layout { this._position = new LayoutPosition(this._store); } - public init(params: LayoutParams, options: LayoutOptions = {}): void { - this._store.create(params); - this.setFollowNode(options.getFollowNode); + public init(params: LayoutParams, options: LayoutOptions): void { + this._store.create(params, options); } public layout(): void { @@ -39,20 +38,4 @@ export class Layout { } return await this._position.position(); } - - public setFollowNode(getFollowNode?: GetFollowNode): void { - if (!getFollowNode) return; - const context = { store: this._store }; - this._store.nodes.forEach((node) => { - const followTo = getFollowNode(node, context)?.followTo; - if (!followTo) return; - const followToNode = this._store.getNode(followTo); - if (!followToNode) return; - if (!followToNode.followedBy) { - followToNode.followedBy = []; - } - followToNode.followedBy.push(node.id); - node.followTo = followTo; - }); - } } diff --git a/packages/plugins/free-auto-layout-plugin/src/layout/position.ts b/packages/plugins/free-auto-layout-plugin/src/layout/position.ts index 1ef94e81..2f7db158 100644 --- a/packages/plugins/free-auto-layout-plugin/src/layout/position.ts +++ b/packages/plugins/free-auto-layout-plugin/src/layout/position.ts @@ -13,6 +13,19 @@ export class LayoutPosition { constructor(private readonly store: LayoutStore) {} public async position(): Promise { + if (this.store.options.enableAnimation) { + return this.positionWithAnimation(); + } + return this.positionDirectly(); + } + + private positionDirectly(): void { + this.store.nodes.forEach((layoutNode) => { + this.updateNodePosition({ layoutNode, step: 100 }); + }); + } + + private async positionWithAnimation(): Promise { return new Promise((resolve) => { startTween({ from: { d: 0 }, diff --git a/packages/plugins/free-auto-layout-plugin/src/layout/store.ts b/packages/plugins/free-auto-layout-plugin/src/layout/store.ts index 357ee615..1415f497 100644 --- a/packages/plugins/free-auto-layout-plugin/src/layout/store.ts +++ b/packages/plugins/free-auto-layout-plugin/src/layout/store.ts @@ -10,7 +10,14 @@ import { } from '@flowgram.ai/free-layout-core'; import { FlowNodeBaseType, FlowNodeTransformData } from '@flowgram.ai/document'; -import type { LayoutConfig, LayoutEdge, LayoutNode, LayoutParams } from './type'; +import type { + GetFollowNode, + LayoutConfig, + LayoutEdge, + LayoutNode, + LayoutOptions, + LayoutParams, +} from './type'; interface LayoutStoreData { nodes: Map; @@ -26,6 +33,8 @@ export class LayoutStore { private container: WorkflowNodeEntity; + public options: LayoutOptions; + constructor(public readonly config: LayoutConfig) {} public get initialized(): boolean { @@ -56,9 +65,10 @@ export class LayoutStore { return Array.from(this.store.edges.values()); } - public create(params: LayoutParams): void { + public create(params: LayoutParams, options: LayoutOptions): void { this.store = this.createStore(params); this.indexMap = this.createIndexMap(); + this.setOptions(options); this.init = true; } @@ -279,4 +289,27 @@ export class LayoutStore { return uniqueNodeIds; } + + /** 记录运行选项 */ + private setOptions(options: LayoutOptions): void { + this.options = options; + this.setFollowNode(options.getFollowNode); + } + + /** 设置跟随节点配置 */ + private setFollowNode(getFollowNode?: GetFollowNode): void { + if (!getFollowNode) return; + const context = { store: this }; + this.nodes.forEach((node) => { + const followTo = getFollowNode(node, context)?.followTo; + if (!followTo) return; + const followToNode = this.getNode(followTo); + if (!followToNode) return; + if (!followToNode.followedBy) { + followToNode.followedBy = []; + } + followToNode.followedBy.push(node.id); + node.followTo = followTo; + }); + } } diff --git a/packages/plugins/free-auto-layout-plugin/src/layout/type.ts b/packages/plugins/free-auto-layout-plugin/src/layout/type.ts index 0818c469..25677a49 100644 --- a/packages/plugins/free-auto-layout-plugin/src/layout/type.ts +++ b/packages/plugins/free-auto-layout-plugin/src/layout/type.ts @@ -71,6 +71,7 @@ export interface LayoutParams { export interface LayoutOptions { getFollowNode?: GetFollowNode; + enableAnimation: boolean; } export interface LayoutConfig { diff --git a/packages/plugins/free-auto-layout-plugin/src/services.ts b/packages/plugins/free-auto-layout-plugin/src/services.ts index 24d51175..85da3828 100644 --- a/packages/plugins/free-auto-layout-plugin/src/services.ts +++ b/packages/plugins/free-auto-layout-plugin/src/services.ts @@ -13,6 +13,7 @@ import { import { AutoLayoutOptions } from './type'; import { LayoutConfig } from './layout/type'; +import { DefaultLayoutOptions } from './layout/constant'; import { DefaultLayoutConfig, Layout, type LayoutOptions } from './layout'; @injectable() @@ -28,8 +29,11 @@ export class AutoLayoutService { }; } - public async layout(options: LayoutOptions = {}): Promise { - await this.layoutNode(this.document.root, options); + public async layout(options: Partial = {}): Promise { + await this.layoutNode(this.document.root, { + ...DefaultLayoutOptions, + ...options, + }); } private async layoutNode(node: WorkflowNodeEntity, options: LayoutOptions): Promise {