refactor(web): 拆分 PluginGraphPage 为 graph 子模块 — 每个文件 < 800 行
- graphTypes.ts (39 行) — GraphNode/GraphEdge/GraphConfig/NodePosition/HoverState - graphLayout.ts (41 行) — computeCircularLayout 环形布局算法 - graphRenderer.ts (293 行) — Canvas 绘制函数 + 常量 + helper - PluginGraphPage.tsx (758 行) — 组件壳:state/effects/event handlers/JSX
This commit is contained in:
41
apps/web/src/pages/graph/graphLayout.ts
Normal file
41
apps/web/src/pages/graph/graphLayout.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 关系图谱 — 布局算法
|
||||
*
|
||||
* 纯函数模块,不依赖 React。
|
||||
*/
|
||||
|
||||
import type { GraphNode, NodePosition } from './graphTypes';
|
||||
|
||||
/**
|
||||
* 计算环形布局位置。
|
||||
*
|
||||
* 节点均匀分布在以 (centerX, centerY) 为圆心、radius 为半径的圆周上。
|
||||
* 单个节点退化为圆心;两个及以上节点按角度排列,起始角在正上方 (-PI/2)。
|
||||
*/
|
||||
export function computeCircularLayout(
|
||||
nodes: GraphNode[],
|
||||
centerX: number,
|
||||
centerY: number,
|
||||
radius: number,
|
||||
): Map<string, NodePosition> {
|
||||
const positions = new Map<string, NodePosition>();
|
||||
const count = nodes.length;
|
||||
if (count === 0) return positions;
|
||||
|
||||
if (count === 1) {
|
||||
positions.set(nodes[0].id, { x: centerX, y: centerY, vx: 0, vy: 0 });
|
||||
return positions;
|
||||
}
|
||||
|
||||
nodes.forEach((node, i) => {
|
||||
const angle = (2 * Math.PI * i) / count - Math.PI / 2;
|
||||
positions.set(node.id, {
|
||||
x: centerX + radius * Math.cos(angle),
|
||||
y: centerY + radius * Math.sin(angle),
|
||||
vx: 0,
|
||||
vy: 0,
|
||||
});
|
||||
});
|
||||
|
||||
return positions;
|
||||
}
|
||||
Reference in New Issue
Block a user