5.0版本动态添加元素边,拖拽和缩放画布之后边错位,如果在新增边也是错位的 #6031
silentRiding posted onGitHub
Describe the bug / 问题描述
5.0版本使用react创建的元素,给元素添加新增删除按钮,动态添加元素和边之后,拖拽和缩放画布之后边出现错位,如果再新增元素,边也是错位的
Reproduction link / 重现链接
No response
Steps to Reproduce the Bug or Issue / 重现步骤
`` 这是index页面 import { Graph, ExtensionCategory, register, CanvasEvent } from '@antv/g6'; import { useEffect, useRef, useState } from 'react'; import { ReactNode, GNode } from '@antv/g6-extension-react'; import InitNode from './initNode'; import AddNode from './addNode';
register(ExtensionCategory.NODE, 'react', ReactNode); export default () => { const [startPoint, setStartPoint] = useState({ x: 0, y: 0 }); const containerRef = useRef<HTMLDivElement>(null); const documentClientHeight = document.documentElement.clientHeight - 20; const documentClientWidth = document.documentElement.clientWidth - 20; useEffect(() => { const graph = new Graph({ container: containerRef.current!, width: 5000, height: 5000, // background: '#ECECEC', // autoFit: { // type: 'view', // options: { // direction: 'both', // when: 'always' // } // }, data: { nodes: [ { id: 'node-1', type: 'react', style: { x: documentClientWidth / 2 - 200, y: 100 }, data: { isInit: true }, } ], edges: [ // { // id: 'edge-1', source: 'node-1', target: 'node-2' // }, // { // id: 'edge-2', source: 'node-1', target: 'node-3' // }, // { // id: 'edge-3', source: 'node-1', target: 'node-4' // } ], }, node: { // type: 'react', style: { size: [426, 100], component: (data: any) => { // 判断加载初始节点/新增节点 if (Object.prototype.toString.call(data.data.isInit) === '[object Boolean]' && data.data.isInit) { return <InitNode data={data} graph={graph} /> } else { return <AddNode data={data} graph={graph} /> } }, ports: [{ placement: 'top' }, { placement: 'bottom' }], }, }, edge: { type: 'cubic-vertical', // style: { // endArrow: true, // }, }, // 通过插件实现背景色 plugins: [ { type: 'background', width: 5000 + 'px', height: 5000 + 'px', background: '#ECECEC', } ], behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'], }); console.log(graph, 'graph') graph.on(CanvasEvent.DRAG_START, (evt) => { const { x, y } = evt.offset; // graph.translateTo([x, y]) setStartPoint({ x, y }); console.log(evt, 'offset') // 更新画布中所有节点的位置 // graph.getNodes().forEach(node => { // const model = node.getModel(); // graph.update(node, { // x: model.x + dx, // y: model.y + dy, // }); // }); }); graph.on(CanvasEvent.DRAG_END, ({ offset }) => { const { x, y } = offset; const dx = x - startPoint.x; const dy = y - startPoint.y; console.log(graph.getNodeData()); // 更新画布中所有节点的位置 graph.getNodeData().forEach(({ id }) => { // graph.translateElementBy( id, [dx, dy]) }) const newEdgeData: any = [] graph.getEdgeData().forEach(({ id, source, target }) => { newEdgeData.push({ id, source, target }) }) graph.updateNodeData([...graph.getNodeData()]) graph.updateEdgeData([...newEdgeData]) // graph.updateData([...graph.getData()]) // graph.translateBy([dx, dy]) graph.updateTransform({ key: 'matrix', translateX: 200, translateY: -10, scaleX: 1.5, scaleY: 1, rotation: 45, // 45度顺时针旋转 }) // graph.render(); }); graph.render(); }, []);
return <div ref={containerRef} />;
};
这是组件页面 addNode组件 import { PlusOutlined, CloseOutlined } from '@ant-design/icons'; import { Button } from 'antd'; import { useState } from 'react';
interface EdgeData { id: string; source: string; target: string; }
export default function AddNode(props: any): JSX.Element {
const [isShow, setIsShow] = useState(false);
// 点击新增按钮
const handlerAddNode = () => {
const { x, y } = props.data.style
const newPosition = calculateLocation(props.data.id)
const nodeData = {
id: node_${new Date().getTime()}
,
type: 'react',
style: { x: newPosition.newX ? newPosition.newX : x - 200, y: newPosition.newY ? newPosition.newY : y + 206 },
data: { isInit: false },
}
const edgeData = {
id: edge_${new Date().getTime()}
,
source: props.data.id,
target: nodeData.id
}
props.graph.addNodeData([nodeData])
props.graph.addEdgeData([edgeData])
props.graph.render()
}
// 点击删除按钮
const handlerDelNode = (id: string) => {
handlerEdgeNode(id)
props.graph.removeNodeData([id]);
}
// 删除相关点的所有节点
const handlerEdgeNode = (id: string) => {
const edgeData = props.graph.getEdgeData().filter((item: EdgeData) => item.source === id)
if (edgeData.length) {
edgeData.forEach((item: EdgeData) => {
handlerDelNode(item.target)
})
}
props.graph.render()
}
// 计算新增节点的位置
const calculateLocation = (id: string) => {
const edgeData = props.graph.getEdgeData().filter((item: EdgeData) => item.source === id)
if (edgeData.length) {
const nodeData = props.graph.getNodeData(edgeData[edgeData.length - 1].target)
return {
newX: nodeData.style.x + 430,
newY: nodeData.style.y
}
} else {
return {}
}
}
return (
<div id="add_node" onMouseEnter={() => setIsShow(true)} onMouseLeave={() => setIsShow(false)}>
{isShow ? <div className="add_node_plus">
<Button onClick={handlerAddNode} type="primary" shape="circle" icon={<PlusOutlined />} />
</div> : null}
{isShow ? <div className="add_node_del">
<Button onClick={() => handlerDelNode(props.data.id)} shape="circle" icon={<CloseOutlined style={{ color: '#f5222d' }} />} />
</div> : null}
</div>
);
}
initNode组件
import { PlusOutlined, CloseOutlined } from '@ant-design/icons';
import { Button } from 'antd';
import './index.less';
import { useEffect, useState } from 'react';
interface EdgeData { id: string; source: string; target: string; } // 创建一个新的日期对象,表示当前时间 const currentDate = new Date();
// 获取年、月、日 const year = currentDate.getFullYear(); const month = String(currentDate.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需要加1,然后补齐两位数 const day = String(currentDate.getDate()).padStart(2, '0'); // 补齐两位数的日期
// 获取时、分、秒 const hours = String(currentDate.getHours()).padStart(2, '0'); const minutes = String(currentDate.getMinutes()).padStart(2, '0'); const seconds = String(currentDate.getSeconds()).padStart(2, '0');
// 构造最终的时间字符串
const currentDateTime = ${year}-${month}-${day} ${hours}:${minutes}:${seconds}
;
const DocsPage = (props: any) => {
const [isShow, setIsShow] = useState(false);
// 点击新增按钮
const handlerAddNode = () => {
const { x, y } = props.data.style
const newPosition = calculateLocation(props.data.id)
const nodeData = {
id: node_${new Date().getTime()}
,
type: 'react',
style: { x: newPosition.newX ? newPosition.newX : x - 200, y: newPosition.newY ? newPosition.newY : y + 206 },
data: { isInit: false },
}
const edgeData = {
id: edge_${new Date().getTime()}
,
source: props.data.id,
target: nodeData.id
}
props.graph.addNodeData([nodeData])
props.graph.addEdgeData([edgeData])
props.graph.render()
}
// 计算新增节点的位置
const calculateLocation = (id: string) => {
const edgeData = props.graph.getEdgeData().filter((item: EdgeData) => item.source === id)
if (edgeData.length) {
const nodeData = props.graph.getNodeData(edgeData[edgeData.length - 1].target)
return {
newX: nodeData.style.x + 430,
newY: nodeData.style.y
}
} else {
return {}
}
}
return (
<div>
<div id="init_node" onMouseEnter={() => setIsShow(true)} onMouseLeave={() => setIsShow(false)}>
<p className="init-node-p">任务开始时间: {currentDateTime}</p>
{isShow ? <div className="add_node_plus">
<Button onClick={handlerAddNode} type="primary" shape="circle" icon={<PlusOutlined />} />
</div> : null}
{/* {isShow ? <div className="add_node_del">
<Button onClick={handlerDelNode} shape="circle" icon={<CloseOutlined style={{ color: '#f5222d' }} />} />
</div> : null} */}
</div>
</div>
);
};
export default DocsPage;
G6 Version / G6 版本
🆕 5.x
Operating System / 操作系统
Windows
Browser / 浏览器
Chrome
Additional context / 补充说明
No response