使用G6绘制关系图谱 (完整代码)

参考具体配置参考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、使用

你可能感兴趣的:(javascript,前端,react.js,g,图形渲染)