|
|
@@ -330,8 +330,58 @@ export function useCanvasLogic(connections, externalControllerRef, nodes = []) {
|
|
|
return { width: 180, height: isVariable ? 40 : 100 };
|
|
|
};
|
|
|
|
|
|
- // 计算端口位置(精确对齐到端口中心)
|
|
|
+ // 计算端口位置(精确对齐到端口中心)- 优先从 DOM 获取实际坐标
|
|
|
const getPortCenterPosition = (node, port, isInput) => {
|
|
|
+ // 尝试从 DOM 获取端口内圆点/箭头的实际位置
|
|
|
+ if (canvasRef.current) {
|
|
|
+ const nodeElement = canvasRef.current.querySelector(`[data-node-id="${node.id}"]`);
|
|
|
+ if (nodeElement) {
|
|
|
+ // 查找所有端口元素
|
|
|
+ const portElements = nodeElement.querySelectorAll('.Blueprint-node-port');
|
|
|
+
|
|
|
+ // 根据端口类型筛选
|
|
|
+ const isExecutionPort = port.type === 'execution';
|
|
|
+ const matchingPorts = Array.from(portElements).filter(portEl => {
|
|
|
+ const isInputPort = portEl.classList.contains('input');
|
|
|
+ const isOutputPort = portEl.classList.contains('output');
|
|
|
+ const isExecPort = portEl.classList.contains('port-execution');
|
|
|
+
|
|
|
+ // 匹配方向和类型
|
|
|
+ const directionMatch = (isInput && isInputPort) || (!isInput && isOutputPort);
|
|
|
+ const typeMatch = isExecutionPort ? isExecPort : !isExecPort;
|
|
|
+
|
|
|
+ return directionMatch && typeMatch;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 根据端口索引获取对应的端口元素
|
|
|
+ const ports = isInput
|
|
|
+ ? (node.inputs || []).filter(p => isExecutionPort ? p.type === 'execution' : p.type !== 'execution')
|
|
|
+ : (node.outputs || []).filter(p => isExecutionPort ? p.type === 'execution' : p.type !== 'execution');
|
|
|
+ const portIndex = ports.findIndex(p => p.id === port.id);
|
|
|
+
|
|
|
+ if (portIndex >= 0 && portIndex < matchingPorts.length) {
|
|
|
+ const portEl = matchingPorts[portIndex];
|
|
|
+ // 查找端口内的圆点或箭头元素
|
|
|
+ const dotElement = portEl.querySelector('.Blueprint-node-port-dot');
|
|
|
+ const arrowElement = portEl.querySelector('.Blueprint-node-port-arrow');
|
|
|
+ const targetElement = dotElement || arrowElement;
|
|
|
+
|
|
|
+ if (targetElement) {
|
|
|
+ // 获取圆点/箭头相对于画布的位置
|
|
|
+ const targetRect = targetElement.getBoundingClientRect();
|
|
|
+ const canvasRect = canvasRef.current.getBoundingClientRect();
|
|
|
+
|
|
|
+ // 计算相对于画布的中心坐标,并考虑画布的 transform
|
|
|
+ const centerX = (targetRect.left + targetRect.width / 2 - canvasRect.left) / transform.scale - transform.translateX / transform.scale;
|
|
|
+ const centerY = (targetRect.top + targetRect.height / 2 - canvasRect.top) / transform.scale - transform.translateY / transform.scale;
|
|
|
+
|
|
|
+ return { x: centerX, y: centerY };
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果无法从 DOM 获取,使用计算值作为后备
|
|
|
const isVariable = node.type === 'variable';
|
|
|
const nodeDims = getNodeDimensions(node.id);
|
|
|
|
|
|
@@ -344,13 +394,9 @@ export function useCanvasLogic(connections, externalControllerRef, nodes = []) {
|
|
|
|
|
|
if (isInput) {
|
|
|
// Set 变量节点的输入端口(左侧)
|
|
|
- // CSS: left: -8px,端口容器左边缘在 node.x - 8
|
|
|
- // 圆点在容器内居中,圆点中心 = node.x - 8 + 8 = node.x
|
|
|
return { x: node.x - 8 + portContainerHalfWidth, y: portY };
|
|
|
} else {
|
|
|
// Get 变量节点的输出端口(右侧)
|
|
|
- // CSS: right: -8px,端口容器右边缘在 node.x + width + 8
|
|
|
- // 圆点在容器内居中,圆点中心 = node.x + width + 8 - 8 = node.x + width
|
|
|
return { x: node.x + nodeDims.width + 8 - portContainerHalfWidth, y: portY };
|
|
|
}
|
|
|
} else {
|
|
|
@@ -410,7 +456,9 @@ export function useCanvasLogic(connections, externalControllerRef, nodes = []) {
|
|
|
|
|
|
// 每个端口的Y位置 = 参数区域起始Y + 索引 * (行高 + 间距) + 行高/2
|
|
|
const paramsStartY = node.y + headerHeight + executionHeight + paramsTopPadding;
|
|
|
- portCenterY = paramsStartY + dataPortIndex * (portRowHeight + portGap) + portRowHeight / 2;
|
|
|
+ // 增加额外偏移量让Y坐标更准确对齐圆点中心
|
|
|
+ const extraYOffset = 4;
|
|
|
+ portCenterY = paramsStartY + dataPortIndex * (portRowHeight + portGap) + portRowHeight / 2 + extraYOffset;
|
|
|
|
|
|
// 圆点直径12px,半径6px
|
|
|
const dotRadius = 6;
|