力导向布局 自定义节点后 防止重叠失效 #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
屏幕截图或视频(可选)
补充说明(可选)
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;