返回顶部
d

dagre-react-flowdagre自动布局

Automatic graph layout using dagre with React Flow (@xyflow/react). Use when implementing auto-layout, hierarchical layouts, tree structures, or arranging nodes programmatically. Triggers on dagre, auto-layout, automatic layout, getLayoutedElements, rankdir, hierarchical graph.

作者: admin | 来源: ClawHub
源自
ClawHub
版本
V 1.1.0
安全检测
已通过
99
下载量
免费
免费
0
收藏
概述
安装方式
版本历史

dagre-react-flow

Dagre与React Flow结合使用

Dagre是一个用于布局有向图的JavaScript库。它可以计算层级/树形布局的最优节点位置。React Flow负责渲染,dagre负责定位。

快速开始

bash
pnpm add @dagrejs/dagre

typescript
import dagre from @dagrejs/dagre;
import { Node, Edge } from @xyflow/react;

const getLayoutedElements = (
nodes: Node[],
edges: Edge[],
direction: TB | LR = TB
) => {
const g = new dagre.graphlib.Graph();
g.setGraph({ rankdir: direction });
g.setDefaultEdgeLabel(() => ({}));

nodes.forEach((node) => {
g.setNode(node.id, { width: 172, height: 36 });
});

edges.forEach((edge) => {
g.setEdge(edge.source, edge.target);
});

dagre.layout(g);

const layoutedNodes = nodes.map((node) => {
const pos = g.node(node.id);
return {
...node,
position: { x: pos.x - 86, y: pos.y - 18 }, // 居中转换为左上角
};
});

return { nodes: layoutedNodes, edges };
};

核心概念

坐标系差异

关键点: Dagre返回中心坐标;React Flow使用左上角坐标。

typescript
// Dagre输出:节点中心
const dagrePos = g.node(nodeId); // { x: 100, y: 50 } = 中心点

// React Flow期望:左上角
const rfPosition = {
x: dagrePos.x - nodeWidth / 2,
y: dagrePos.y - nodeHeight / 2,
};

节点尺寸

Dagre需要明确的尺寸。三种方法:

1. 固定尺寸(最简单):
typescript
g.setNode(node.id, { width: 172, height: 36 });

2. 从数据中获取每个节点的尺寸:
typescript
g.setNode(node.id, {
width: node.data.width ?? 172,
height: node.data.height ?? 36,
});

3. 测量尺寸(最准确):
typescript
// React Flow测量节点后
g.setNode(node.id, {
width: node.measured?.width ?? 172,
height: node.measured?.height ?? 36,
});

布局方向

方向使用场景
TB从上到下组织结构图、决策树
BT
从下到上 | 依赖关系图(依赖项在底部) | | LR | 从左到右 | 时间线、水平流程图 | | RL | 从右到左 | 从右到左布局 |

typescript
g.setGraph({ rankdir: LR }); // 水平布局

完整实现

基础布局函数

typescript
import dagre from @dagrejs/dagre;
import type { Node, Edge } from @xyflow/react;

interface LayoutOptions {
direction?: TB | BT | LR | RL;
nodeWidth?: number;
nodeHeight?: number;
nodesep?: number; // 水平间距
ranksep?: number; // 垂直间距(层级之间)
}

export function getLayoutedElements(
nodes: Node[],
edges: Edge[],
options: LayoutOptions = {}
): { nodes: Node[]; edges: Edge[] } {
const {
direction = TB,
nodeWidth = 172,
nodeHeight = 36,
nodesep = 50,
ranksep = 50,
} = options;

const g = new dagre.graphlib.Graph();
g.setGraph({ rankdir: direction, nodesep, ranksep });
g.setDefaultEdgeLabel(() => ({}));

nodes.forEach((node) => {
const width = node.measured?.width ?? nodeWidth;
const height = node.measured?.height ?? nodeHeight;
g.setNode(node.id, { width, height });
});

edges.forEach((edge) => {
g.setEdge(edge.source, edge.target);
});

dagre.layout(g);

const layoutedNodes = nodes.map((node) => {
const pos = g.node(node.id);
const width = node.measured?.width ?? nodeWidth;
const height = node.measured?.height ?? nodeHeight;

return {
...node,
position: {
x: pos.x - width / 2,
y: pos.y - height / 2,
},
};
});

return { nodes: layoutedNodes, edges };
}

React Flow集成

tsx
import { useCallback } from react;
import {
ReactFlow,
useNodesState,
useEdgesState,
useReactFlow,
ReactFlowProvider,
} from @xyflow/react;
import { getLayoutedElements } from ./layout;

const initialNodes = [
{ id: 1, data: { label: 开始 }, position: { x: 0, y: 0 } },
{ id: 2, data: { label: 处理 }, position: { x: 0, y: 0 } },
{ id: 3, data: { label: 结束 }, position: { x: 0, y: 0 } },
];

const initialEdges = [
{ id: e1-2, source: 1, target: 2 },
{ id: e2-3, source: 2, target: 3 },
];

// 应用初始布局
const { nodes: layoutedNodes, edges: layoutedEdges } = getLayoutedElements(
initialNodes,
initialEdges,
{ direction: TB }
);

function Flow() {
const [nodes, setNodes, onNodesChange] = useNodesState(layoutedNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(layoutedEdges);
const { fitView } = useReactFlow();

const onLayout = useCallback((direction: TB | LR) => {
const { nodes: newNodes, edges: newEdges } = getLayoutedElements(
nodes,
edges,
{ direction }
);

setNodes([...newNodes]);
setEdges([...newEdges]);

// 布局后自适应视图并添加动画
window.requestAnimationFrame(() => {
fitView({ duration: 300 });
});
}, [nodes, edges, setNodes, setEdges, fitView]);

return (






nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
fitView
/>

);
}

export default function App() {
return (



);
}

useAutoLayout Hook

可复用的自动布局Hook:

typescript
import { useCallback, useEffect, useRef } from react;
import {
useReactFlow,
useNodesInitialized,
type Node,
type Edge,
} from @xyflow/react;
import dagre from @dagrejs/dagre;

interface UseAutoLayoutOptions {
direction?: TB | BT | LR | RL;
nodesep?: number;
ranksep?: number;
}

export function useAutoLayout(options: UseAutoLayoutOptions = {}) {
const { direction = TB, nodesep = 50, ranksep = 50 } = options;
const { getNodes, getEdges, setNodes, fitView } = useReactFlow();
const nodesInitialized = useNodesInitialized();
const layoutApplied = useRef(false);

const runLayout = useCallback(() => {
const nodes = getNodes();
const edges = getEdges();

const g = new dagre.graphlib.Graph();
g.setGraph({ rankdir: direction, nodesep, ranksep });
g.setDefaultEdgeLabel(() => ({}));

nodes.forEach((node) => {
g.setNode(node.id, {
width: node.measured?.width ?? 172,
height: node.measured?.height ?? 36,
});
});

edges.forEach((edge) => {
g.setEdge(edge.source, edge.target);
});

dagre.layout(g);

const layouted = nodes.map((node) => {
const pos = g.node(node.id);
const width = node.measured?.width ??

标签

skill ai

通过对话安装

该技能支持在以下平台通过对话安装:

OpenClaw WorkBuddy QClaw Kimi Claude

方式一:安装 SkillHub 和技能

帮我安装 SkillHub 和 dagre-react-flow-1775982668 技能

方式二:设置 SkillHub 为优先技能安装源

设置 SkillHub 为我的优先技能安装源,然后帮我安装 dagre-react-flow-1775982668 技能

通过命令行安装

skillhub install dagre-react-flow-1775982668

下载

⬇ 下载 dagre-react-flow v1.1.0(免费)

文件大小: 7 KB | 发布时间: 2026-4-13 09:57

v1.1.0 最新 2026-4-13 09:57
- Improved and expanded documentation in SKILL.md, including detailed usage instructions, advanced configuration, and clear integration examples with React Flow.
- Added complete code examples for layout functions, React Flow integration, and a reusable useAutoLayout hook.
- Clarified core concepts such as coordinate system differences, node dimensions, and layout directions.
- Enhanced guidance on auto-layout, hierarchical layouts, and working with measured node sizes.
- Documentation now provides both quick start and deep-dive implementation details for all major use cases.

Archiver·手机版·闲社网·闲社论坛·羊毛社区· 多链控股集团有限公司 · 苏ICP备2025199260号-1

Powered by Discuz! X5.0   © 2024-2025 闲社网·线报更新论坛·羊毛分享社区·http://xianshe.com

p2p_official_large
返回顶部