free-stack-plugin.mdx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import { PackageManagerTabs } from '@theme';
  2. # @flowgram.ai/free-stack-plugin
  3. 层级管理插件,为自由布局画布提供节点和连线的 z-index 层级控制功能。
  4. ## 功能
  5. - 智能计算节点和连线的层级关系,避免遮挡问题
  6. - 支持选中节点自动置顶显示
  7. - 支持悬停节点和连线的高亮显示
  8. - 可自定义节点排序规则,控制同层级节点的渲染顺序
  9. - 自动处理父子节点的层级关系
  10. - 支持连线的智能层级管理,确保连线可见性
  11. - 实时响应节点选择、悬停和实体变化事件
  12. ## 快速开始
  13. 1. 安装
  14. <PackageManagerTabs command="install @flowgram.ai/free-stack-plugin" />
  15. 2. 注册插件
  16. 插件的注册方法和 flowgram 的其他插件基本相同,只需要保证不要重复创建以及最终传入到对应的 FreeLayoutEditorProvider 即可
  17. ```tsx
  18. import { createFreeStackPlugin } from '@flowgram.ai/free-stack-plugin';
  19. const editorProps = useMemo(() => ({
  20. plugins: () => [
  21. createFreeStackPlugin()
  22. ]
  23. }), []);
  24. return (
  25. <FreeLayoutEditorProvider {...editorProps}>
  26. <EditorRenderer />
  27. </FreeLayoutEditorProvider>
  28. )
  29. ```
  30. 3. 自定义节点排序
  31. 可以通过 `sortNodes` 函数自定义同层级节点的排序规则:
  32. ```tsx
  33. import { createFreeStackPlugin } from '@flowgram.ai/free-stack-plugin';
  34. import { WorkflowNodeType } from './nodes/constants';
  35. const editorProps = useMemo(() => ({
  36. plugins: () => [
  37. createFreeStackPlugin({
  38. sortNodes: (nodes) => {
  39. const commentNodes = [];
  40. const otherNodes = [];
  41. // 将注释节点和其他节点分开
  42. nodes.forEach((node) => {
  43. if (node.flowNodeType === WorkflowNodeType.Comment) {
  44. commentNodes.push(node);
  45. } else {
  46. otherNodes.push(node);
  47. }
  48. });
  49. // 注释节点渲染在底层,其他节点在上层
  50. return [...commentNodes, ...otherNodes];
  51. },
  52. })
  53. ]
  54. }), []);
  55. ```
  56. ## 配置选项
  57. ### FreeStackPluginOptions
  58. 插件的配置选项:
  59. ```typescript
  60. interface FreeStackPluginOptions {
  61. /** 自定义节点排序函数 */
  62. sortNodes?: (nodes: WorkflowNodeEntity[]) => WorkflowNodeEntity[];
  63. }
  64. ```
  65. ### sortNodes 函数
  66. 用于自定义同层级节点的排序规则:
  67. ```typescript
  68. type SortNodesFunction = (nodes: WorkflowNodeEntity[]) => WorkflowNodeEntity[];
  69. ```
  70. **参数说明:**
  71. - `nodes`: 需要排序的节点数组
  72. - **返回值**: 排序后的节点数组
  73. **使用场景:**
  74. - 将特定类型的节点(如注释)放在底层
  75. - 按照业务优先级排序节点
  76. - 按照创建时间或其他属性排序
  77. ## 层级管理算法
  78. ### 基础层级计算
  79. 插件使用智能算法计算每个节点和连线的层级:
  80. 1. **基础层级**:从 `BASE_Z_INDEX`(默认为 8)开始计算
  81. 2. **节点层级**:根据节点的嵌套关系和排序规则计算
  82. 3. **连线层级**:确保连线不被节点遮挡,同时处理特殊情况
  83. ### 层级提升规则
  84. 以下情况会触发层级提升:
  85. - **选中节点**:选中的节点会被提升到顶层
  86. - **悬停元素**:悬停的节点或连线会被高亮显示
  87. - **正在绘制的连线**:绘制中的连线会置于顶层
  88. - **父子关系连线**:父子节点间的连线会优先显示
  89. ### 层级计算流程
  90. 1. **初始化**:清除缓存,计算基础参数
  91. 2. **节点索引**:建立节点索引映射
  92. 3. **选中节点处理**:标记选中节点的父级关系
  93. 4. **层级分配**:递归处理节点层级
  94. 5. **连线处理**:计算连线层级,确保可见性
  95. 6. **样式应用**:将计算结果应用到 DOM 元素
  96. ## 高级用法
  97. ### 复杂排序规则
  98. 可以实现复杂的节点排序逻辑:
  99. ```typescript
  100. const sortNodes = (nodes: WorkflowNodeEntity[]) => {
  101. return nodes.sort((a, b) => {
  102. // 1. 按节点类型优先级排序
  103. const typeOrder = {
  104. [WorkflowNodeType.Comment]: 0,
  105. [WorkflowNodeType.Start]: 1,
  106. [WorkflowNodeType.End]: 2,
  107. // ... 其他类型
  108. };
  109. const aOrder = typeOrder[a.flowNodeType] ?? 999;
  110. const bOrder = typeOrder[b.flowNodeType] ?? 999;
  111. if (aOrder !== bOrder) {
  112. return aOrder - bOrder;
  113. }
  114. // 2. 按创建时间排序
  115. return a.createTime - b.createTime;
  116. });
  117. };
  118. ```
  119. ## 常见问题
  120. ### Q: 如何让特定类型的节点始终在底层?
  121. A: 通过 `sortNodes` 函数将这些节点排在数组前面:
  122. ```typescript
  123. const sortNodes = (nodes) => {
  124. const backgroundNodes = nodes.filter(node =>
  125. node.flowNodeType === WorkflowNodeType.Comment
  126. );
  127. const foregroundNodes = nodes.filter(node =>
  128. node.flowNodeType !== WorkflowNodeType.Comment
  129. );
  130. return [...backgroundNodes, ...foregroundNodes];
  131. };
  132. ```
  133. ### Q: 如何禁用自动层级管理?
  134. A: 目前插件没有提供禁用选项,如果需要完全自定义层级管理,建议不使用此插件,直接在节点组件中设置 z-index。
  135. ### Q: 性能优化建议?
  136. A: 插件已经内置了性能优化:
  137. - 使用防抖机制减少计算频率
  138. - 只在必要时重新计算层级
  139. - 使用 Map 数据结构提高查找效率
  140. 对于大型画布(超过 1000 个节点),建议:
  141. - 简化 `sortNodes` 函数的逻辑
  142. - 避免在排序函数中进行复杂计算