参考具体配置参考G6官网
1、配置文件
export const getGraphConfig = (
width: number,
height: number,
elementId: string,
direction?: string,
) => {
return {
container: elementId,
width,
height,
fitView: true,
fitCenter: true,
layout: {
type: 'dagre',
rankdir: direction ? direction : 'LR',
align: 'DL',
controlPoints: true,
preventOverlap: true,
nodesep: 20,
ranksep: 100,
},
defaultNode: {
size: [200, 40],
type: 'node-child',
anchorPoints: [
[1, 0.5],
[1, 0],
],
},
defaultEdge: {
// type: 'line-arrow',
type: 'cubic-horizontal',
size: 1,
color: '#5DB1B1',
style: {
endArrow: {
path: 'M 0,0 L 12,6 L 9,0 L 12,-6 Z',
fill: '#5DB1B1',
},
radius: 20,
},
sourceAnchor: direction === 'RL' ? 0 : 1,
targetAnchor: direction === 'RL' ? 1 : 0,
},
};
};
//根据数据计算画布宽高,自动滚动到根节点
export const fitView = (chartBox: any, container: any, graph: any, direction: 'RL' | 'LR') => {
const timer = setTimeout(() => {
const nodesPositionList = graph
?.getNodes?.()
?.map((node: any) => node?._cfg?.group?.getCanvasBBox?.());
const sortedX = [...nodesPositionList]?.sort((cur: any, pre: any) => pre?.x - cur?.x);
const sortedY = [...nodesPositionList]?.sort((cur: any, pre: any) => pre?.y - cur?.y);
const rightNode = sortedX?.[0];
const leftNode = sortedX?.[sortedX?.length - 1];
const width = rightNode?.maxX - leftNode?.minX + 48;
const topNode = sortedY?.[sortedY?.length - 1];
const bottomNode = sortedY?.[0];
const height = bottomNode?.maxY - topNode?.minY;
const containerWidth = container?.clientWidth;
const containerHeight = container?.clientHeight;
const curWidth = width > containerWidth ? width : containerWidth;
const curHeight = height > containerHeight ? height : containerHeight;
if (curHeight && curWidth) {
graph.changeSize(curWidth, curHeight);
graph.fitView();
chartBox.scrollBy(direction === 'LR' ? 0 : curWidth, 0);
}
clearTimeout(timer);
}, 200);
};
2、自定义节点
import React from 'react';
import { Rect, Text, Group, Image } from '@antv/g6-react-node';
import { nullIf } from '@/utils/tools';
import icon from '@/assets/images/indicator/icon.png';
import iconActive from '@/assets/images/indicator/icon_active.png';
interface Props {
cfg: any;
}
export default function NodeChild({ cfg }: Props) {
const { name, id: code, index, onDBClick } = cfg;
const cursor = onDBClick && index !== 0 ? 'pointer' : 'default';
const handleDBClick = (v: string) => {
if (index !== 0) {
onDBClick?.(v);
}
};
return (
handleDBClick(code)}
>
onDBClick?.(code)}
>
{nullIf(name)}
);
}
3、 封装的组件
import React, { useEffect, useRef } from 'react';
import { appenAutoShapeListener, createNodeFromReact } from '@antv/g6-react-node';
import G6 from '@antv/g6';
import { useDeepCompareEffect } from 'ahooks';
import NodeChild from './NodeChild';
import { fitView, getGraphConfig } from './config';
import styles from './index.less';
interface Props {
elementId: string;
dataSource?: any;
direction?: 'RL' | 'LR';
style?: React.CSSProperties;
onNodeClick?: (code: string) => void;
}
const createNode = (Component: any, onDBClick: any) => {
return function (props: any) {
return ;
};
};
const RelationChart: React.FC = ({
elementId,
dataSource,
direction = 'LR',
style,
onNodeClick,
}) => {
const containerRef = useRef();
const graphRef = useRef();
useEffect(() => {
if (dataSource?.nodes?.length && !graphRef.current) {
const container: any = document.getElementById(elementId);
const width = container?.clientWidth;
G6.registerNode('node-child', createNodeFromReact(createNode(NodeChild, onNodeClick)));
// G6.registerEdge('line-arrow', arrowLine, 'line');
const cfg = getGraphConfig(
width,
container?.parentNode?.clientHeight - 32,
elementId,
direction,
);
graphRef.current = new G6.Graph(cfg);
}
}, [dataSource, elementId, direction, onNodeClick]);
useDeepCompareEffect(() => {
const graph = graphRef.current;
if (graph) {
graph?.clear();
graph?.data(dataSource);
graph?.setMinZoom(1);
graph?.setMaxZoom(1);
graph?.render();
// @ts-ignore
appenAutoShapeListener(graph);
fitView(containerRef?.current, document.getElementById(elementId), graph, direction);
}
}, [dataSource]);
return (
);
};
export default RelationChart;
4、测试数据
export const data = {
nodes: [
{
id: '0',
label: '测试测试-0',
index: 0,
},
{
id: '1',
label: '测试测试-1',
},
{
id: '2',
label: '测试测试-2',
},
{
id: '3',
label: '测试测试测试测试测试测试-3',
},
{
id: '4',
label: '测试测试-4',
},
{
id: '5',
label: '测试测试测试测试-5',
},
{
id: '6',
label: '测试测试-6',
},
{
id: '7',
label: '测试测试-7',
},
{
id: '8',
label: '测试测试-8',
},
{
id: '9',
label: '测试测试-9',
},
{
id: '10',
label: '测试测试-10',
},
],
edges: [
{
source: '0',
target: '1',
},
{
source: '6',
target: '2',
},
{
source: '1',
target: '4',
},
{
source: '0',
target: '3',
},
{
source: '3',
target: '4',
},
{
source: '4',
target: '5',
},
{
source: '4',
target: '6',
},
{
source: '5',
target: '7',
},
{
source: '5',
target: '8',
},
{
source: '8',
target: '9',
},
{
source: '2',
target: '9',
},
{
source: '9',
target: '10',
},
],
};
4、使用