Skip to content

Commit b978ff5

Browse files
committed
feat: 新增泳道插件
1 parent 0f5fd6a commit b978ff5

22 files changed

Lines changed: 3223 additions & 4 deletions

File tree

examples/feature-examples/.umirc.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ export default defineConfig({
9090
name: '自定义主题',
9191
component: './nodes/custom/theme',
9292
},
93+
{
94+
path: '/custom-nodes/new-pool',
95+
name: '新泳道节点',
96+
component: './nodes/custom/pool',
97+
},
9398
],
9499
},
95100
{

examples/feature-examples/src/pages/graph/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import centerAnchorRect from './nodes/centerAnchorRect'
3333
import GraphData = LogicFlow.GraphData
3434
import styles from './index.less'
3535

36-
import OnDragNodeConfig = LogicFlow.OnDragNodeConfig
36+
// import OnDragNodeConfig = LogicFlow.OnDragNodeConfig
3737

3838
const NodeComponent: FC<ReactNodeProps> = ({ node }) => {
3939
const data = node.getData()
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const data = {
2+
nodes: [
3+
// {
4+
// id: 'pool-1',
5+
// type: 'customPool',
6+
// x: 400,
7+
// y: 200,
8+
// width: 600,
9+
// height: 300,
10+
// children: ['lane-1'],
11+
// properties: {
12+
// name: '泳池示例',
13+
// layoutDirection: 'horizontal',
14+
// },
15+
// },
16+
// {
17+
// id: 'lane-1',
18+
// type: 'customLane',
19+
// x: 400,
20+
// y: 200,
21+
// width: 600,
22+
// height: 300,
23+
// properties: {
24+
// name: '泳道示例',
25+
// layoutDirection: 'horizontal',
26+
// },
27+
// }
28+
],
29+
edges: [],
30+
}
31+
32+
export default data
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
.pool-demo-container {
2+
display: flex;
3+
flex-direction: column;
4+
height: 100vh;
5+
padding: 20px;
6+
background: #fff;
7+
8+
.demo-header {
9+
margin-bottom: 20px;
10+
text-align: center;
11+
12+
h2 {
13+
margin: 0 0 8px;
14+
color: #262626;
15+
font-weight: 600;
16+
font-size: 24px;
17+
}
18+
19+
p {
20+
margin: 0;
21+
color: #8c8c8c;
22+
font-size: 14px;
23+
}
24+
}
25+
26+
.demo-content {
27+
flex: 1;
28+
overflow: hidden;
29+
border: 1px solid #e8e8e8;
30+
border-radius: 6px;
31+
32+
.pool-demo-graph {
33+
width: 100%;
34+
height: 100%;
35+
}
36+
}
37+
38+
.demo-footer {
39+
margin-top: 20px;
40+
padding: 16px;
41+
background: #f9f9f9;
42+
border-radius: 6px;
43+
44+
h3 {
45+
margin: 0 0 12px;
46+
color: #262626;
47+
font-weight: 600;
48+
font-size: 16px;
49+
}
50+
51+
ul {
52+
margin: 0;
53+
padding-left: 20px;
54+
55+
li {
56+
margin: 4px 0;
57+
color: #595959;
58+
font-size: 14px;
59+
}
60+
}
61+
}
62+
}
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
import React, { useEffect, useRef } from 'react'
2+
import LogicFlow from '@logicflow/core'
3+
import { Flex } from 'antd'
4+
import { PoolElements } from '@logicflow/extension'
5+
import data from './newData'
6+
import '@logicflow/core/dist/index.css'
7+
import './index.less'
8+
9+
const config = {
10+
grid: true,
11+
background: {
12+
color: '#f5f5f5',
13+
},
14+
keyboard: {
15+
enabled: true,
16+
},
17+
}
18+
19+
const PoolNodeDemo: React.FC = () => {
20+
const containerRef = useRef<HTMLDivElement>(null)
21+
const lfRef = useRef<LogicFlow>()
22+
23+
const handleDragItem = (node: any) => {
24+
lfRef?.current?.dnd.startDrag(node)
25+
}
26+
const handleGetGraphData = () => {
27+
console.log('lf', lfRef.current?.getGraphData(), lfRef.current?.graphModel)
28+
}
29+
30+
useEffect(() => {
31+
console.log('useEffect run')
32+
if (!containerRef.current) return
33+
34+
const lf = new LogicFlow({
35+
...config,
36+
container: containerRef.current,
37+
width: 1200,
38+
height: 1200,
39+
allowResize: true,
40+
allowRotate: true,
41+
plugins: [PoolElements],
42+
})
43+
44+
// 注册泳池和泳道节点
45+
// registerPoolNodes(lf)
46+
lf.on('node:click', ({ data }) => {
47+
const clickNodeModel = lf.getNodeModelById(data.id)
48+
console.log(
49+
'点击了节点',
50+
clickNodeModel,
51+
clickNodeModel?.zIndex,
52+
lf.graphModel.nodes.map((node) => `${node.id}-${node.zIndex}`),
53+
)
54+
if (clickNodeModel?.isLane) {
55+
const parentModel = lf.getNodeModelById(
56+
clickNodeModel.properties.parent,
57+
)
58+
console.log('parentModel', parentModel?.zIndex)
59+
}
60+
})
61+
lf.on('edge:add', ({ data }) => {
62+
console.log('添加了边', data)
63+
const { id } = data
64+
const edgeModel = lf.getEdgeModelById(id)
65+
console.log('边的层级', edgeModel?.zIndex)
66+
})
67+
68+
lf.render(data)
69+
console.log('lf', lf.getGraphData())
70+
71+
lfRef.current = lf
72+
73+
return () => {
74+
lfRef.current?.destroy()
75+
}
76+
}, [])
77+
78+
return (
79+
<div className="pool-demo-container">
80+
<div className="demo-header">
81+
<h2>泳池和泳道节点示例</h2>
82+
<p>基于动态分组插件和内置resizable能力重新实现</p>
83+
<div style={{ marginTop: '10px' }}>
84+
<span>当前图ID: {lfRef.current?.flowId}</span>
85+
<Flex wrap="wrap" gap="small" justify="center" align="center">
86+
<div
87+
className="dnd-item wrapper"
88+
onMouseDown={() =>
89+
handleDragItem({
90+
type: 'rect',
91+
text: 'rect',
92+
})
93+
}
94+
>
95+
矩形
96+
</div>
97+
<div
98+
className="dnd-item wrapper"
99+
onMouseDown={() => {
100+
handleDragItem({
101+
type: 'circle',
102+
text: 'circle',
103+
})
104+
}}
105+
>
106+
圆形
107+
</div>
108+
<div
109+
className="dnd-item wrapper"
110+
onMouseDown={() => {
111+
handleDragItem({
112+
type: 'diamond',
113+
text: 'diamond',
114+
})
115+
}}
116+
>
117+
菱形
118+
</div>
119+
<div
120+
className="dnd-item wrapper"
121+
onMouseDown={() => {
122+
handleDragItem({
123+
type: 'ellipse',
124+
text: 'ellipse',
125+
properties: {
126+
rx: 40,
127+
ry: 80,
128+
},
129+
})
130+
}}
131+
>
132+
椭圆
133+
</div>
134+
<div
135+
className="dnd-item wrapper"
136+
onMouseDown={() => {
137+
handleDragItem({
138+
type: 'html',
139+
text: 'html',
140+
})
141+
}}
142+
>
143+
html
144+
</div>
145+
<div
146+
className="dnd-item wrapper"
147+
onMouseDown={() => {
148+
handleDragItem({
149+
type: 'polygon',
150+
text: 'polygon',
151+
properties: {
152+
width: 110,
153+
height: 100,
154+
style: {
155+
fill: '#ffd591',
156+
stroke: '#ffa940',
157+
strokeWidth: 2,
158+
fillRule: 'evenodd',
159+
},
160+
},
161+
})
162+
}}
163+
>
164+
多边形
165+
</div>
166+
<div
167+
className="dnd-item text"
168+
onMouseDown={() => {
169+
handleDragItem({
170+
type: 'text',
171+
text: '文本',
172+
})
173+
}}
174+
>
175+
文本
176+
</div>
177+
<div
178+
className="dnd-item text"
179+
onMouseDown={() => {
180+
handleDragItem({
181+
type: 'pool',
182+
text: '横向泳池',
183+
properties: {
184+
width: 400,
185+
height: 200,
186+
direction: 'horizontal',
187+
laneConfig: {
188+
text: '水平泳道',
189+
},
190+
},
191+
})
192+
}}
193+
>
194+
横向泳道
195+
</div>
196+
<div
197+
className="dnd-item text"
198+
onMouseDown={() => {
199+
handleDragItem({
200+
type: 'pool',
201+
text: '竖向泳池',
202+
properties: {
203+
width: 200,
204+
height: 400,
205+
direction: 'vertical',
206+
laneConfig: {
207+
text: '水平泳道',
208+
},
209+
},
210+
})
211+
}}
212+
>
213+
竖向泳道
214+
</div>
215+
<div className="dnd-item text" onClick={handleGetGraphData}>
216+
获取图数据
217+
</div>
218+
</Flex>
219+
</div>
220+
</div>
221+
<div className="demo-content">
222+
<div
223+
ref={containerRef}
224+
className="pool-demo-graph"
225+
style={{
226+
width: '100%',
227+
height: '1200px',
228+
}}
229+
/>
230+
</div>
231+
</div>
232+
)
233+
}
234+
235+
export default PoolNodeDemo

0 commit comments

Comments
 (0)