Skip to content

Commit

Permalink
feat: 来源去向图自定义展开方向 (#1980)
Browse files Browse the repository at this point in the history
  • Loading branch information
DawnLck committed Jul 7, 2023
1 parent fd5118b commit b4df3da
Show file tree
Hide file tree
Showing 7 changed files with 413 additions and 105 deletions.
2 changes: 1 addition & 1 deletion packages/graphs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@antv/dom-util": "^2.0.4",
"@antv/g6": "^4.2.4",
"@antv/layout": "^0.1.17",
"@antv/util": "^2.0.9",
"@antv/util": "^2.0.17",
"insert-css": "^2.0.0",
"react-content-loader": "^5.0.4"
},
Expand Down
239 changes: 149 additions & 90 deletions packages/graphs/src/components/flow-analysis-graph/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,152 @@ export const bindEvents = (params: {
fetchLoading?: FetchLoading;
}) => {
const { graph, level, asyncData, fetchLoading } = params;

const changeData = (data, eventData?: FlowGraphDatum) => {
if (eventData) graph.set('eventData', new EventData(eventData));
graph.changeData(data);
if (graph.get('fitCenter')) {
graph.fitCenter();
}
};

/**
* 通过递归获取所有关联的需要更新的节点
* @param nodeId 目标节点ID
* @param fullEdges 所有的边数据
* @param expandDirection 展开收起的方向,也会决定递归的方向
* @returns
*/
const getNodeTargets = (nodeId: string, fullEdges: any[], expandDirection: 'left' | 'right' = 'right') => {
let allTargets = [];

const getLinkedId = (currentId: string) => {
fullEdges.forEach((edge) => {
const { source, target } = edge;

switch (expandDirection) {
case 'left':
if (target === currentId && !allTargets.includes(source)) {
allTargets.push(source);
getLinkedId(source);
}
break;
case 'right':
if (source === currentId && !allTargets.includes(target)) {
allTargets.push(target);
getLinkedId(target);
}
break;
default:
}
});
};

getLinkedId(nodeId as string);

// 避免成环的情况
allTargets = allTargets.filter((t) => t !== nodeId);

return allTargets;
};

/**
*
* @param e 事件对象
* @param nodeId 当前节点的ID
* @param collapsed 当前折叠状态,handle时要反着处理
* @returns
*/
const handleNodeCollapse = async (e: IG6GraphEvent, nodeId: string, collapsed: boolean) => {
const markerCfg = graph?.['cfg']?.markerCfg;
const controlData: { edges: any[]; nodes: any[] } = graph.get('eventData').getData();
const { edges: fullEdges = [], nodes: fullNodes } = controlData ?? {};
const item = e.item as INode;
const markerCfgValue = typeof markerCfg === 'function' ? markerCfg(item.getModel(), item.get('group')) : markerCfg;

let allTargets = getNodeTargets(nodeId, fullEdges, markerCfgValue?.expandDirection ?? 'right');

// 展开 / 收起 逻辑部分
if (!collapsed) {
// collapse
graph.findAll('node', (node) => allTargets.includes(node.get('id'))).forEach((node) => graph.hideItem(node));
fullNodes.forEach((node: CollapsedNode) => {
const { collapsedLevel = 0, id } = node;
if (allTargets.includes(id)) {
node.collapsedLevel = collapsedLevel + 1;
}
});
} else {
const { nodes: currentNodes, edges: currentEdges } = graph.get('data');
if (allTargets.length) {
// 已经展开过
if (graph.findById(allTargets[0])) {
allTargets.forEach((id) => {
const n = graph.findById(id);
if (n) {
const { collapsedLevel } = n.getModel();
if (!collapsedLevel || (collapsedLevel as number) < 2) graph.showItem(n);
}
});
fullNodes.forEach((node: CollapsedNode) => {
const { collapsedLevel = 0, id } = node;
if (allTargets.includes(id)) {
node.collapsedLevel = collapsedLevel - 1;
}
});
} else {
// 从全量 data 中取
let concatNodes;
if (level) {
concatNodes = fullNodes.filter((n) => {
return allTargets.includes(n.id) && n[`${prefix}_level`] === model[`${prefix}_level`] + 1;
});
allTargets = concatNodes.map((n) => n.id);
}

const currentData = {
nodes: currentNodes
.map((n) => {
if (n.id === nodeId) n[`${prefix}_children`] = allTargets;
return n;
})
.concat(concatNodes),
edges: currentEdges.concat(fullEdges.filter((e) => e.source === nodeId)),
};
changeData(currentData);
}
} else if (asyncData) {
createFetchLoading(item.getModel() as NodeConfig, fetchLoading);
const { nodes: asnycNodes, edges: asyncEdges } = await asyncData(item.getModel() as NodeConfig);
// modify current node collapsed status
graph.updateItem(item, {
collapsed: false,
});
graph.refreshItem(item);
closeFetchLoading();
const getDataByEvent = (nodes, edges) => {
return {
nodes: nodes
.map((n) => {
if (n.id === nodeId) n[`${prefix}_children`] = asnycNodes.map((n) => n.id);
return n;
})
.concat(asnycNodes),
edges: edges.concat(
asyncEdges?.length ? asyncEdges : asnycNodes.map((t) => ({ source: nodeId, target: t.id })),
),
};
};
changeData(getDataByEvent(currentNodes, currentEdges), getDataByEvent(fullNodes, fullEdges));
graph.emit(MARKER_CLICK, e, {
type: 'fetch',
collapsed: true,
});
return;
}
}
};

const onClick = async (e: IG6GraphEvent) => {
const controlData: { edges: any[]; nodes: any[] } = graph.get('eventData').getData();
if (e.target.get('name')?.startsWith('collapse-icon')) {
Expand All @@ -39,104 +178,22 @@ export const bindEvents = (params: {
const { edges: fullEdges = [], nodes: fullNodes } = controlData ?? {};
const updateItems: INode[] = [];
const updateIds: string[] = [];
let allTargets: string[] = [];
const getLinkedId = (currentId: string) => {
fullEdges.forEach((edge) => {
const { source, target } = edge;
if (source === currentId && !allTargets.includes(target)) {
allTargets.push(target);
getLinkedId(target);
}
});
};
getLinkedId(nodeId as string);
// 避免成环的情况
allTargets = allTargets.filter((t) => t !== nodeId);
if (!collapsed) {
// collapse
graph.findAll('node', (node) => allTargets.includes(node.get('id'))).forEach((node) => graph.hideItem(node));
fullNodes.forEach((node: CollapsedNode) => {
const { collapsedLevel = 0, id } = node;
if (allTargets.includes(id)) {
node.collapsedLevel = collapsedLevel + 1;
}
});
} else {
const { nodes: currentNodes, edges: currentEdges } = graph.get('data');
if (allTargets.length) {
// 已经展开过
if (graph.findById(allTargets[0])) {
allTargets.forEach((id) => {
const n = graph.findById(id);
if (n) {
const { collapsedLevel } = n.getModel();
if (!collapsedLevel || collapsedLevel < 2) graph.showItem(n);
}
});
fullNodes.forEach((node: CollapsedNode) => {
const { collapsedLevel = 0, id } = node;
if (allTargets.includes(id)) {
node.collapsedLevel = collapsedLevel - 1;
}
});
} else {
// 从全量 data 中取
let concatNodes;
if (level) {
concatNodes = fullNodes.filter((n) => {
return allTargets.includes(n.id) && n[`${prefix}_level`] === model[`${prefix}_level`] + 1;
});
allTargets = concatNodes.map((n) => n.id);
}

const currentData = {
nodes: currentNodes
.map((n) => {
if (n.id === nodeId) n[`${prefix}_children`] = allTargets;
return n;
})
.concat(concatNodes),
edges: currentEdges.concat(fullEdges.filter((e) => e.source === nodeId)),
};
changeData(currentData);
}
} else if (asyncData) {
createFetchLoading(item.getModel() as NodeConfig, fetchLoading);
const { nodes: asnycNodes, edges: asyncEdges } = await asyncData(item.getModel() as NodeConfig);
// modify current node collapsed status
graph.updateItem(item, {
collapsed: false,
});
graph.refreshItem(item);
closeFetchLoading();
const getDataByEvent = (nodes, edges) => {
return {
nodes: nodes
.map((n) => {
if (n.id === nodeId) n[`${prefix}_children`] = asnycNodes.map((n) => n.id);
return n;
})
.concat(asnycNodes),
edges: edges.concat(
asyncEdges?.length ? asyncEdges : asnycNodes.map((t) => ({ source: nodeId, target: t.id })),
),
};
};
changeData(getDataByEvent(currentNodes, currentEdges), getDataByEvent(fullNodes, fullEdges));
graph.emit(MARKER_CLICK, e, {
type: 'fetch',
collapsed: true,
});
return;
}
}
// 处理节点的 展开 / 收起,获取所有待更新节点的数据
handleNodeCollapse(e, nodeId, collapsed);

console.log(fullEdges, nodeId);

// 更新连接边
const { target: updateNodeTarget } = fullEdges.find((edge) => edge.source === nodeId);
fullEdges.forEach((edge) => {
const { source, target } = edge;
if (target === updateNodeTarget) {
updateIds.push(source);
}
});

// 更新节点
Array.from(new Set(updateIds)).forEach((id: string) => {
updateItems.push(graph.find('node', (node) => node.get('id') === id) as INode);
});
Expand All @@ -146,6 +203,8 @@ export const bindEvents = (params: {
});
graph.refreshItem(nodeItem);
});

// 更新marker
graph.emit(MARKER_CLICK, e, {
type: 'collapse',
collapsed: !!collapsed,
Expand Down
16 changes: 7 additions & 9 deletions packages/graphs/src/hooks/useGraphs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,8 @@ export default function useGraph(
if (!graph) {
return;
}
const {
type: edgeType,
style: edgeStyle,
startArrow: startArrowCfg,
endArrow: endArrowCfg,
label: labelCfg,
} = edgeCfg ?? {};
const { type: edgeType, style: edgeStyle, startArrow: startArrowCfg, endArrow: endArrowCfg, label: labelCfg } =
edgeCfg ?? {};
graph.getEdges().forEach((edge: IEdge) => {
// 资金流向图&来源去向图
if (['fund-line', 'labels-line'].includes(edgeType)) {
Expand Down Expand Up @@ -287,7 +282,7 @@ export default function useGraph(
edgeStateStyles,
} = edgeCfg ?? {};

graphRef.current = new G6[graphClass]({
const graphConfig = {
container: container.current as any,
width: graphSize[0],
height: graphSize[1],
Expand All @@ -314,7 +309,10 @@ export default function useGraph(
getChildren,
fetchLoading,
},
});
markerCfg,
};

graphRef.current = new G6[graphClass](graphConfig);
const graphId = getGraphId(graphRef.current, name);
const graph = graphRef.current;
graph.set('id', graphId);
Expand Down
Loading

0 comments on commit b4df3da

Please sign in to comment.