antvis/G6

力导向布局 自定义节点后 防止重叠失效 #5003

liwuli posted onGitHub

问题描述

力导向布局 自定义节点后 防止重叠失效

重现链接

https://codesandbox.io/s/sleepy-grass-rmj3ry?file=/src/App.js

重现步骤

import React,{ useState , useEffect, FC, useRef } from "react"; import ReactDOM from 'react-dom'; import './index.less' import { Select,Radio,Button} from 'antd'; import G6 from '@antv/g6'; import { Rect, Text, Circle, Image, Group, createNodeFromReact, appenAutoShapeListener } from '@antv/g6-react-node'; const Map:FC<any> =()=> { const container = useRef<any>(null); const graph = useRef<any>(null); //全局方法

useEffect(()=>{
    initmap();
},[])

// 
const marjorNode = ({ cfg = {} }:any) => {
  const { id } = cfg;
  return(
    <Group id={id} name={id} draggable>
      <Circle >
        <Image
          style={{
            img: 'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png',
            width: 108,
            height: 108,
            cursor: 'move',
          }}
          draggable
        />
      </Circle>
    </Group>
  )
}


// 注册自定义节点
const registerstyle = () =>{
  G6.registerNode('marjorNode', createNodeFromReact(marjorNode));
}

const initmap = () =>{
    if (graph.current) {
        try {
          graph.current.dispose();

        } catch (error) {
          console.log(error);
        }
      }
    const containerdom: any = ReactDOM.findDOMNode(container.current);
    const width = containerdom.scrollWidth;
    const height = containerdom.scrollHeight || 1000;
    // g6 注册react 组件
    registerstyle();
    // 初始化图        
    graph.current = new G6.Graph({
        container: containerdom,
        width,
        height,
        layout: {
          type: 'force',
          preventOverlap: true,
          linkDistance: (d) => {
            if (d.source.id === 'node0') {
              return 100;
            }
            return 30;
          },
          nodeStrength: (d) => {
            if (d.isLeaf) {
              return -50;
            }
            return -10;
          },
          edgeStrength: (d) => {
            if (d.source.id === 'node1' || d.source.id === 'node2' || d.source.id === 'node3') {
              return 0.7;
            }
            return 0.1;
          },
        },
        defaultNode: {
            color: '#5B8FF9',
        },
        modes: {
            // 'drag-node'
            default: ['zoom-canvas','drag-canvas'],
        },
    });
    const data = {
        nodes: [
          { id: 'node0', size: 108,type:'marjorNode'},
          { id: 'node1', size: 108 },
          { id: 'node2', size: 108 },
          { id: 'node3', size: 108 },
          { id: 'node4', size: 30, isLeaf: true },
          { id: 'node5', size: 30, isLeaf: true },
          { id: 'node6', size: 15, isLeaf: true },
          { id: 'node7', size: 15, isLeaf: true },
          { id: 'node8', size: 15, isLeaf: true },
          { id: 'node9', size: 15, isLeaf: true },
          { id: 'node10', size: 15, isLeaf: true },
          { id: 'node11', size: 15, isLeaf: true },
          { id: 'node12', size: 15, isLeaf: true },
          { id: 'node13', size: 15, isLeaf: true },
          { id: 'node14', size: 15, isLeaf: true },
          { id: 'node15', size: 15, isLeaf: true },
          { id: 'node16', size: 15, isLeaf: true },
        ],
        edges: [
          { source: 'node0', target: 'node1' },
          { source: 'node0', target: 'node2' },
          { source: 'node0', target: 'node3' },
          { source: 'node0', target: 'node4' },
          { source: 'node0', target: 'node5' },
          { source: 'node1', target: 'node6' },
          { source: 'node1', target: 'node7' },
          { source: 'node2', target: 'node8' },
          { source: 'node2', target: 'node9' },
          { source: 'node2', target: 'node10' },
          { source: 'node2', target: 'node11' },
          { source: 'node2', target: 'node12' },
          { source: 'node2', target: 'node13' },
          { source: 'node3', target: 'node14' },
          { source: 'node3', target: 'node15' },
          { source: 'node3', target: 'node16' },
        ],
      };
      const nodes = data.nodes;
      graph.current.data({
        nodes,
        edges: data.edges.map(function (edge, i) {
          edge.id = 'edge' + i;
          return Object.assign({}, edge);
        }),
      });
      graph.current.render();

      graph.current.on('node:dragstart', function (e) {
        graph.current.layout();
        refreshDragedNodePosition(e);
      });
      graph.current.on('node:drag', function (e) {
        const forceLayout = graph.current.get('layoutController').layoutMethods[0];
        forceLayout.execute();
        refreshDragedNodePosition(e);
      });
      graph.current.on('node:dragend', function (e) {
        e.item.get('model').fx = null;
        e.item.get('model').fy = null;
      });

      if (typeof window !== 'undefined'){
        window.onresize = () => {
            if (!graph.current || graph.current.get('destroyed')) return;
            if (!containerdom || !containerdom.scrollWidth || !containerdom.scrollHeight) return;
            graph.current.changeSize(containerdom.scrollWidth, containerdom.scrollHeight);
        };
      };
}

const refreshDragedNodePosition =(e) => {
    const model = e.item.get('model');
    model.fx = e.x;
    model.fy = e.y;
}

return (
    <div className="mapv3_view">
        <div className="map_canvas" ref={container}></div>
    </div>
)

}

export default Map;

预期行为

力导向布局 支持自定义节点 后防重叠

平台

  • 操作系统: Windows
  • 网页浏览器: Google Chrome
  • G6 版本: 4.8.17

屏幕截图或视频(可选)

image

补充说明(可选)

import React,{ useState , useEffect, FC, useRef } from "react"; import ReactDOM from 'react-dom'; import './index.less' import G6 from '@antv/g6'; import { Rect, Text, Circle, Image, Group, createNodeFromReact, appenAutoShapeListener } from '@antv/g6-react-node'; const Map:FC<any> =()=> { const container = useRef<any>(null); const graph = useRef<any>(null); //全局方法

useEffect(()=>{
    initmap();
},[])

// 
const marjorNode = ({ cfg = {} }:any) => {
  const { id } = cfg;
  return(
    <Group id={id} name={id} draggable>
      <Circle >
        <Image
          style={{
            img: 'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png',
            width: 108,
            height: 108,
            cursor: 'move',
          }}
          draggable
        />
      </Circle>
    </Group>
  )
}


// 注册自定义节点
const registerstyle = () =>{
  G6.registerNode('marjorNode', createNodeFromReact(marjorNode));
}

const initmap = () =>{
    if (graph.current) {
        try {
          graph.current.dispose();

        } catch (error) {
          console.log(error);
        }
      }
    const containerdom: any = ReactDOM.findDOMNode(container.current);
    const width = containerdom.scrollWidth;
    const height = containerdom.scrollHeight || 1000;
    // g6 注册react 组件
    registerstyle();
    // 初始化图        
    graph.current = new G6.Graph({
        container: containerdom,
        width,
        height,
        layout: {
          type: 'force',
          preventOverlap: true,
          linkDistance: (d) => {
            if (d.source.id === 'node0') {
              return 100;
            }
            return 30;
          },
          nodeStrength: (d) => {
            if (d.isLeaf) {
              return -50;
            }
            return -10;
          },
          edgeStrength: (d) => {
            if (d.source.id === 'node1' || d.source.id === 'node2' || d.source.id === 'node3') {
              return 0.7;
            }
            return 0.1;
          },
        },
        defaultNode: {
            color: '#5B8FF9',
        },
        modes: {
            // 'drag-node'
            default: ['zoom-canvas','drag-canvas'],
        },
    });
    const data = {
        nodes: [
          { id: 'node0', size: 108,type:'marjorNode'},
          { id: 'node1', size: 108 },
          { id: 'node2', size: 108 },
          { id: 'node3', size: 108 },
          { id: 'node4', size: 30, isLeaf: true },
          { id: 'node5', size: 30, isLeaf: true },
          { id: 'node6', size: 15, isLeaf: true },
          { id: 'node7', size: 15, isLeaf: true },
          { id: 'node8', size: 15, isLeaf: true },
          { id: 'node9', size: 15, isLeaf: true },
          { id: 'node10', size: 15, isLeaf: true },
          { id: 'node11', size: 15, isLeaf: true },
          { id: 'node12', size: 15, isLeaf: true },
          { id: 'node13', size: 15, isLeaf: true },
          { id: 'node14', size: 15, isLeaf: true },
          { id: 'node15', size: 15, isLeaf: true },
          { id: 'node16', size: 15, isLeaf: true },
        ],
        edges: [
          { source: 'node0', target: 'node1' },
          { source: 'node0', target: 'node2' },
          { source: 'node0', target: 'node3' },
          { source: 'node0', target: 'node4' },
          { source: 'node0', target: 'node5' },
          { source: 'node1', target: 'node6' },
          { source: 'node1', target: 'node7' },
          { source: 'node2', target: 'node8' },
          { source: 'node2', target: 'node9' },
          { source: 'node2', target: 'node10' },
          { source: 'node2', target: 'node11' },
          { source: 'node2', target: 'node12' },
          { source: 'node2', target: 'node13' },
          { source: 'node3', target: 'node14' },
          { source: 'node3', target: 'node15' },
          { source: 'node3', target: 'node16' },
        ],
      };
      const nodes = data.nodes;
      graph.current.data({
        nodes,
        edges: data.edges.map(function (edge, i) {
          edge.id = 'edge' + i;
          return Object.assign({}, edge);
        }),
      });
      graph.current.render();

      graph.current.on('node:dragstart', function (e) {
        graph.current.layout();
        refreshDragedNodePosition(e);
      });
      graph.current.on('node:drag', function (e) {
        const forceLayout = graph.current.get('layoutController').layoutMethods[0];
        forceLayout.execute();
        refreshDragedNodePosition(e);
      });
      graph.current.on('node:dragend', function (e) {
        e.item.get('model').fx = null;
        e.item.get('model').fy = null;
      });

      if (typeof window !== 'undefined'){
        window.onresize = () => {
            if (!graph.current || graph.current.get('destroyed')) return;
            if (!containerdom || !containerdom.scrollWidth || !containerdom.scrollHeight) return;
            graph.current.changeSize(containerdom.scrollWidth, containerdom.scrollHeight);
        };
      };
}

const refreshDragedNodePosition =(e) => {
    const model = e.item.get('model');
    model.fx = e.x;
    model.fy = e.y;
}

return (
    <div className="mapv3_view">
        <div className="map_canvas" ref={container}></div>
    </div>
)

}

export default Map;


Fund this Issue

$0.00
Funded

Pull requests