mirror of
https://gitee.com/ByteDance/flowgram.ai.git
synced 2025-07-07 17:43:29 +08:00
fix(core): support hover line or port in deep layer container (#443)
This commit is contained in:
parent
522bc0770d
commit
0a9c3a0167
@ -66,6 +66,8 @@ export class WorkflowLineEntity extends Entity<WorkflowLineEntityOpts> {
|
|||||||
|
|
||||||
private _hasError = false;
|
private _hasError = false;
|
||||||
|
|
||||||
|
public stackIndex = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 线条数据
|
* 线条数据
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { last } from 'lodash-es';
|
|||||||
import { inject, injectable } from 'inversify';
|
import { inject, injectable } from 'inversify';
|
||||||
import { DisposableCollection, Emitter, type IPoint } from '@flowgram.ai/utils';
|
import { DisposableCollection, Emitter, type IPoint } from '@flowgram.ai/utils';
|
||||||
import { FlowNodeRenderData, FlowNodeTransformData } from '@flowgram.ai/document';
|
import { FlowNodeRenderData, FlowNodeTransformData } from '@flowgram.ai/document';
|
||||||
import { EntityManager, PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';
|
import { EntityManager, PlaygroundConfigEntity } from '@flowgram.ai/core';
|
||||||
|
|
||||||
import { WorkflowDocumentOptions } from './workflow-document-option';
|
import { WorkflowDocumentOptions } from './workflow-document-option';
|
||||||
import { type WorkflowDocument } from './workflow-document';
|
import { type WorkflowDocument } from './workflow-document';
|
||||||
@ -416,13 +416,8 @@ export class WorkflowLinesManager {
|
|||||||
.filter((port) => port.node.flowNodeType !== 'root');
|
.filter((port) => port.node.flowNodeType !== 'root');
|
||||||
const targetPort = allPorts.find((port) => port.isHovered(pos.x, pos.y));
|
const targetPort = allPorts.find((port) => port.isHovered(pos.x, pos.y));
|
||||||
if (targetPort) {
|
if (targetPort) {
|
||||||
// 后创建的要先校验
|
const containNodes = this.getContainNodesFromMousePos(pos);
|
||||||
const targetNode = this.document
|
const targetNode = last(containNodes);
|
||||||
.getAllNodes()
|
|
||||||
.slice()
|
|
||||||
.reverse()
|
|
||||||
.filter((node) => targetPort.node?.parent?.id !== node.id)
|
|
||||||
.find((node) => node.getData(TransformData)!.contains(pos.x, pos.y));
|
|
||||||
// 点位可能会被节点覆盖
|
// 点位可能会被节点覆盖
|
||||||
if (targetNode && targetNode !== targetPort.node) {
|
if (targetNode && targetNode !== targetPort.node) {
|
||||||
return;
|
return;
|
||||||
@ -436,27 +431,9 @@ export class WorkflowLinesManager {
|
|||||||
* @param pos - 鼠标位置
|
* @param pos - 鼠标位置
|
||||||
*/
|
*/
|
||||||
getNodeFromMousePos(pos: IPoint): WorkflowNodeEntity | undefined {
|
getNodeFromMousePos(pos: IPoint): WorkflowNodeEntity | undefined {
|
||||||
const allNodes = this.document
|
|
||||||
.getAllNodes()
|
|
||||||
.sort((a, b) => this.getNodeIndex(a) - this.getNodeIndex(b));
|
|
||||||
// 先挑选出 bounds 区域符合的 node
|
// 先挑选出 bounds 区域符合的 node
|
||||||
const containNodes: WorkflowNodeEntity[] = [];
|
|
||||||
const { selection } = this.selectService;
|
const { selection } = this.selectService;
|
||||||
const zoom =
|
const containNodes = this.getContainNodesFromMousePos(pos);
|
||||||
this.entityManager.getEntity<PlaygroundConfigEntity>(PlaygroundConfigEntity)?.config?.zoom ||
|
|
||||||
1;
|
|
||||||
allNodes.forEach((node) => {
|
|
||||||
const { bounds } = node.getData<FlowNodeTransformData>(FlowNodeTransformData);
|
|
||||||
// 交互要求,节点边缘 4px 的时候就生效连线逻辑
|
|
||||||
if (
|
|
||||||
bounds
|
|
||||||
.clone()
|
|
||||||
.pad(4 / zoom)
|
|
||||||
.contains(pos.x, pos.y)
|
|
||||||
) {
|
|
||||||
containNodes.push(node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 当有元素被选中的时候选中元素在顶层
|
// 当有元素被选中的时候选中元素在顶层
|
||||||
if (selection?.length) {
|
if (selection?.length) {
|
||||||
const filteredNodes = containNodes.filter((node) =>
|
const filteredNodes = containNodes.filter((node) =>
|
||||||
@ -479,6 +456,31 @@ export class WorkflowLinesManager {
|
|||||||
line.addData(WorkflowLineRenderData);
|
line.addData(WorkflowLineRenderData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 获取鼠标坐标位置的所有节点(stackIndex 从小到大排序) */
|
||||||
|
private getContainNodesFromMousePos(pos: IPoint): WorkflowNodeEntity[] {
|
||||||
|
const allNodes = this.document
|
||||||
|
.getAllNodes()
|
||||||
|
.sort((a, b) => this.getNodeIndex(a) - this.getNodeIndex(b));
|
||||||
|
const zoom =
|
||||||
|
this.entityManager.getEntity<PlaygroundConfigEntity>(PlaygroundConfigEntity)?.config?.zoom ||
|
||||||
|
1;
|
||||||
|
const containNodes = allNodes
|
||||||
|
.map((node) => {
|
||||||
|
const { bounds } = node.getData<FlowNodeTransformData>(FlowNodeTransformData);
|
||||||
|
// 交互要求,节点边缘 4px 的时候就认为选中节点
|
||||||
|
if (
|
||||||
|
bounds
|
||||||
|
.clone()
|
||||||
|
.pad(4 / zoom)
|
||||||
|
.contains(pos.x, pos.y)
|
||||||
|
) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Boolean) as WorkflowNodeEntity[];
|
||||||
|
return containNodes;
|
||||||
|
}
|
||||||
|
|
||||||
private getNodeIndex(node: WorkflowNodeEntity): number {
|
private getNodeIndex(node: WorkflowNodeEntity): number {
|
||||||
const nodeRenderData = node.getData(FlowNodeRenderData);
|
const nodeRenderData = node.getData(FlowNodeRenderData);
|
||||||
return nodeRenderData.stackIndex;
|
return nodeRenderData.stackIndex;
|
||||||
|
|||||||
@ -236,38 +236,32 @@ export class HoverLayer extends Layer<HoverLayerOptions> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const nodeInContainer = !!(nodeHovered?.parent && nodeHovered.parent.flowNodeType !== 'root');
|
|
||||||
|
|
||||||
// 获取最接近的线条
|
// 获取最接近的线条
|
||||||
// 线条会相交需要获取最接近点位的线条,不能删除的线条不能被选中
|
// 线条会相交需要获取最接近点位的线条,不能删除的线条不能被选中
|
||||||
const lineHovered = checkTargetFromLine
|
const lineHovered = checkTargetFromLine
|
||||||
? this.linesManager.getCloseInLineFromMousePos(mousePos)
|
? this.linesManager.getCloseInLineFromMousePos(mousePos)
|
||||||
: undefined;
|
: undefined;
|
||||||
const lineInContainer = !!lineHovered?.inContainer;
|
|
||||||
|
|
||||||
// 判断容器内节点是否 hover
|
if (nodeHovered && lineHovered) {
|
||||||
if (nodeHovered && nodeInContainer) {
|
const nodeStackIndex = nodeHovered.renderData.stackIndex;
|
||||||
this.updateHoveredKey(nodeHovered.id);
|
const lineStackIndex = lineHovered.stackIndex;
|
||||||
return;
|
if (nodeStackIndex > lineStackIndex) {
|
||||||
}
|
return this.updateHoveredKey(nodeHovered.id);
|
||||||
// 判断容器内线条是否 hover
|
} else {
|
||||||
if (lineHovered && lineInContainer) {
|
return this.updateHoveredKey(lineHovered.id);
|
||||||
this.updateHoveredKey(lineHovered.id);
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断节点是否 hover
|
// 判断节点是否 hover
|
||||||
if (nodeHovered) {
|
if (nodeHovered) {
|
||||||
this.updateHoveredKey(nodeHovered.id);
|
return this.updateHoveredKey(nodeHovered.id);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// 判断线条是否 hover
|
// 判断线条是否 hover
|
||||||
if (lineHovered) {
|
if (lineHovered) {
|
||||||
this.hoverService.updateHoveredKey(lineHovered.id);
|
return this.updateHoveredKey(lineHovered.id);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上述逻辑都未命中 则清空 hoverd
|
// 上述逻辑都未命中 则清空 hovered
|
||||||
hoverService.clearHovered();
|
hoverService.clearHovered();
|
||||||
|
|
||||||
const currentState = this.editorStateConfig.getCurrentState();
|
const currentState = this.editorStateConfig.getCurrentState();
|
||||||
|
|||||||
@ -80,23 +80,26 @@ export class StackingContextManager {
|
|||||||
const element = nodeRenderData.node;
|
const element = nodeRenderData.node;
|
||||||
element.style.position = 'absolute';
|
element.style.position = 'absolute';
|
||||||
if (level === undefined) {
|
if (level === undefined) {
|
||||||
element.style.zIndex = 'auto';
|
|
||||||
nodeRenderData.stackIndex = 0;
|
nodeRenderData.stackIndex = 0;
|
||||||
|
element.style.zIndex = 'auto';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const stackIndex = StackingConfig.startIndex + level;
|
nodeRenderData.stackIndex = level;
|
||||||
element.style.zIndex = String(stackIndex);
|
const zIndex = StackingConfig.startIndex + level;
|
||||||
nodeRenderData.stackIndex = stackIndex;
|
element.style.zIndex = String(zIndex);
|
||||||
});
|
});
|
||||||
this.lines.forEach((line) => {
|
this.lines.forEach((line) => {
|
||||||
const level = lineLevel.get(line.id);
|
const level = lineLevel.get(line.id);
|
||||||
const element = line.node;
|
const element = line.node;
|
||||||
element.style.position = 'absolute';
|
element.style.position = 'absolute';
|
||||||
if (level === undefined) {
|
if (level === undefined) {
|
||||||
|
line.stackIndex = 0;
|
||||||
element.style.zIndex = 'auto';
|
element.style.zIndex = 'auto';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
element.style.zIndex = String(StackingConfig.startIndex + level);
|
line.stackIndex = level;
|
||||||
|
const zIndex = StackingConfig.startIndex + level;
|
||||||
|
element.style.zIndex = String(zIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user