chore(examples): add layouting with new api

This commit is contained in:
moklick
2021-11-02 12:52:24 +01:00
parent 6e3ff4e849
commit 65991de037
8 changed files with 120 additions and 94 deletions
+4 -1
View File
@@ -19,7 +19,10 @@ import ReactFlow, {
import ColorSelectorNode from './ColorSelectorNode';
const onLoad = (reactFlowInstance: OnLoadParams) => console.log('flow loaded:', reactFlowInstance);
const onLoad = (reactFlowInstance: OnLoadParams) => {
console.log('flow loaded:', reactFlowInstance);
reactFlowInstance.fitView();
};
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
+99
View File
@@ -0,0 +1,99 @@
import { useState, useCallback } from 'react';
import ReactFlow, {
ReactFlowProvider,
addEdge,
applyNodeChanges,
applyEdgeChanges,
Controls,
NodeChange,
EdgeChange,
Node,
Connection,
Edge,
NodeExtent,
Position,
} from 'react-flow-renderer';
import dagre from 'dagre';
import initialNodesAndEdges from './initial-elements';
import './layouting.css';
const dagreGraph = new dagre.graphlib.Graph();
dagreGraph.setDefaultEdgeLabel(() => ({}));
const nodeExtent: NodeExtent = [
[0, 0],
[1000, 1000],
];
const LayoutFlow = () => {
const [nodes, setNodes] = useState<Node[]>(initialNodesAndEdges.nodes);
const [edges, setEdges] = useState<Edge[]>(initialNodesAndEdges.edges);
const onConnect = useCallback((params: Edge | Connection) => {
setEdges((eds) => {
return addEdge(params, eds);
});
}, []);
const onLayout = (direction: string) => {
const isHorizontal = direction === 'LR';
dagreGraph.setGraph({ rankdir: direction });
nodes.forEach((node) => {
dagreGraph.setNode(node.id, { width: 150, height: 50 });
});
edges.forEach((edge) => {
dagreGraph.setEdge(edge.source, edge.target);
});
dagre.layout(dagreGraph);
const layoutedNodes = nodes.map((node) => {
const nodeWithPosition = dagreGraph.node(node.id);
node.targetPosition = isHorizontal ? Position.Left : Position.Top;
node.sourcePosition = isHorizontal ? Position.Right : Position.Bottom;
// we need to pass a slightly different position in order to notify react flow about the change
// @TODO how can we change the position handling so that we dont need this hack?
node.position = { x: nodeWithPosition.x + Math.random() / 1000, y: nodeWithPosition.y };
return node;
});
setNodes(layoutedNodes);
};
const onNodesChange = useCallback((changes: NodeChange[]) => setNodes((ns) => applyNodeChanges(changes, ns)), []);
const onEdgesChange = useCallback((changes: EdgeChange[]) => {
setEdges((es) => applyEdgeChanges(changes, es));
}, []);
return (
<div className="layoutflow">
<ReactFlowProvider>
<ReactFlow
nodes={nodes}
edges={edges}
onConnect={onConnect}
nodeExtent={nodeExtent}
onLoad={() => onLayout('TB')}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
>
<Controls />
</ReactFlow>
<div className="controls">
<button onClick={() => onLayout('TB')} style={{ marginRight: 10 }}>
vertical layout
</button>
<button onClick={() => onLayout('LR')}>horizontal layout</button>
</div>
</ReactFlowProvider>
</div>
);
};
export default LayoutFlow;
+76
View File
@@ -0,0 +1,76 @@
import { Node, Edge, XYPosition } from 'react-flow-renderer';
const position: XYPosition = { x: 0, y: 0 };
const nodes: Node[] = [
{
id: '1',
type: 'input',
data: { label: 'input' },
position,
},
{
id: '2',
data: { label: 'node 2' },
position,
},
{
id: '2a',
data: { label: 'node 2a' },
position,
},
{
id: '2b',
data: { label: 'node 2b' },
position,
},
{
id: '2c',
data: { label: 'node 2c' },
position,
},
{
id: '2d',
data: { label: 'node 2d' },
position,
},
{
id: '3',
data: { label: 'node 3' },
position,
},
{
id: '4',
data: { label: 'node 4' },
position,
},
{
id: '5',
data: { label: 'node 5' },
position,
},
{
id: '6',
type: 'output',
data: { label: 'output' },
position,
},
{ id: '7', type: 'output', data: { label: 'output' }, position: { x: 400, y: 450 } },
];
const edges: Edge[] = [
{ id: 'e12', source: '1', target: '2', type: 'smoothstep' },
{ id: 'e13', source: '1', target: '3', type: 'smoothstep' },
{ id: 'e22a', source: '2', target: '2a', type: 'smoothstep' },
{ id: 'e22b', source: '2', target: '2b', type: 'smoothstep' },
{ id: 'e22c', source: '2', target: '2c', type: 'smoothstep' },
{ id: 'e2c2d', source: '2c', target: '2d', type: 'smoothstep' },
{ id: 'e45', source: '4', target: '5', type: 'smoothstep' },
{ id: 'e56', source: '5', target: '6', type: 'smoothstep' },
{ id: 'e57', source: '5', target: '7', type: 'smoothstep' },
];
const nodesAndEdges = { nodes, edges };
export default nodesAndEdges;
+11
View File
@@ -0,0 +1,11 @@
.layoutflow {
flex-grow: 1;
position: relative;
}
.layoutflow .controls {
position: absolute;
right: 10px;
top: 10px;
z-index: 10;
}
+6 -1
View File
@@ -1,4 +1,4 @@
import React, { ChangeEvent } from 'react';
import { ChangeEvent } from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, Switch, withRouter } from 'react-router-dom';
@@ -7,6 +7,7 @@ import UpdateNode from './UpdateNode';
import Stress from './Stress';
import CustomNode from './CustomNode';
import FloatingEdges from './FloatingEdges';
import Layouting from './Layouting';
import './index.css';
@@ -31,6 +32,10 @@ const routes = [
path: '/floating-edges',
component: FloatingEdges,
},
{
path: '/layouting',
component: Layouting,
},
];
const Header = withRouter(({ history, location }) => {