JavaScript is required

节点碰撞检测与位移限制

带碰撞检测的节点拖拽

演示高级节点拖拽功能,包括碰撞检测、通过颜色编码的视觉反馈、重叠防止,以及在节点放置到有效目标上时自动创建连接。

带碰撞检测的节点拖拽

功能概述

本示例演示了高级节点拖拽功能,包括碰撞检测、重叠防止和动态连接创建。当拖动节点到其他节点上方时,系统通过颜色变化提供视觉反馈,并在释放时自动创建节点间的连接。

核心特性实现

拖拽事件处理器

const onNodeDragging = (node: RGNode, newX: number, newY: number, buffX: number, buffY: number, e: RGUserEvent) => {
    let rejectOverlaped = false;
    let limitedPosition: RGCoordinate | undefined;

    const allNodes = graphInstance.getNodes();
    for (const n of allNodes) {
        if (node.id === n.id) continue;

        // 检查重叠
        const overlap = MyRelationGraphUtils.shapesOverlap(nodeBox, n, shapeA, shapeB);
        if (overlap) {
            // 为不同行为进行颜色编码
            let newColor = n.data!.allowDrop ? 'rgba(212,252,189,0.82)' : 'rgba(252,189,189,0.82)';

            if (n.data.disallowDroppingNodesInside) {
                rejectOverlaped = true;
                limitedPosition = MyRelationGraphUtils.getNoOverlapLimitedPosition(node, newX, newY, n);
                newColor = 'rgba(214,165,246,0.82)';
            }

            graphInstance.updateNode(n, { color: newColor });
        }
    }

    if (rejectOverlaped) {
        return limitedPosition; // 防止重叠
    }
};

拖拽开始和结束处理器

const onNodeDragStart = (nodeObject: RGNode) => {
    graphInstance.updateNodeData(nodeObject, {
        startX: nodeObject.x,
        startY: nodeObject.y
    });
};

const onNodeDragEnd = (nodeObject: RGNode) => {
    const allNodes = graphInstance.getNodes();
    for (const n of allNodes) {
        if (nodeObject.id === n.id) continue;

        const overlap = MyRelationGraphUtils.shapesOverlap(nodeObject, n, nodeObject.nodeShape, n.nodeShape);
        if (overlap) {
            updateNodeAsChildren(nodeObject, n);
            break;
        }
    }
};

连接创建

const updateNodeAsChildren = (node: RGNode, parentNode: RGNode) => {
    // 恢复位置
    graphInstance.updateNodePosition(node, node.data!.startX, node.data!.startY);
    // 添加连接线
    graphInstance.addLines([{
        id: `new_l_${Date.now()}`,
        from: parentNode.id,
        to: node.id,
        text: 'New Relationship',
        color: 'rgba(214,165,246,0.82)',
        lineWidth: 3
    }]);
};

配置界面

<SimpleUIBoolean
    label="Disallow Dropping Nodes Inside"
    currentValue={node.data.disallowDroppingNodesInside}
    onChange={(newValue) => {
        graphInstance.updateNodeData(node, {disallowDroppingNodesInside: newValue})
    }}
/>

创意使用场景

工作流设计器:将任务拖到泳道或类别上以自动分配。绿色显示有效放置目标,红色显示无效目标。

数据库架构设计器:将表拖到其他表上以创建外键关系。重叠防止维护布局完整性,连接创建建立关系。

思维导图:将概念拖到类别上以自动组织。节点可以配置为接受或拒绝某些类型的内容。

看板:在列之间拖动卡片或将卡片拖到特定团队成员。碰撞检测防止卡片放置在无效位置。

组织架构图:将员工拖到部门以重新分配他们。视觉反馈指示有效的部门调动。

项目规划:将里程碑拖到阶段以安排它们。重叠拒绝防止调度冲突,有效放置创建层次关系。

游戏关卡编辑器:将游戏对象拖到图层或区域上。不同颜色指示不同对象类型的有效放置区域。

电路设计:将组件拖到板或子电路上。碰撞检测防止组件重叠,有效放置创建电气连接。