JavaScript is required

自定义全屏目标容器

这个示例展示如何通过 `fullscreenElementXPath` 将 relation-graph 内置全屏行为重定向到更大的外层容器。一个小型左到右树图位于说明头部与两侧面板之间,使全屏边界清晰可见,便于在更复杂页面布局中复用。

将全屏重定向到页面级图外层容器

这个示例构建了什么

这个示例在一个全页外层容器中构建了一棵小型的从左到右树形图,该容器还包含说明文字和两个固定侧边面板。可见界面刻意保持简洁:一个页头、一个绿色提示区块、中间的图,以及左右两侧的占位块。

用户可以点击节点并使用 relation-graph 内置工具栏。这里最重要的交互是全屏按钮,因为这个 demo 让全屏范围包含周围的外层内容,而不是只把图画布单独全屏。

重点不在树本身。重点在于当 relation-graph 进入全屏模式时,如何让相邻的页面 UI 继续保持可见。

数据是如何组织的

图数据直接在 initializeGraph() 中以内联方式声明为一个 RGJsonData 对象,包含 rootId: 'a'、一个扁平的 nodes 数组和一个扁平的 lines 数组。它描述了一棵紧凑的分支树,共有 16 个节点和 15 条连接。

在加载数据之前,代码会执行一步预处理:为任何尚未拥有 id 的 line 赋值 line-${index}。之后,这份数据集会直接传给 setJsonData(),中间没有 fetch 步骤、适配层或派生视图模型。

在真实应用中,同样的数据结构可以表示审批链、组件依赖树、组织分支,或任何其他需要出现在更大页面布局中的小型关系集合。

relation-graph 是如何使用的

index.tsx 使用 RGProvider 包裹整个示例,MyGraph.tsx 则通过 RGHooks.useGraphInstance() 获取当前激活的图实例。一个仅在挂载时执行的 useEffect() 会运行 initializeGraph(),随后通过 setJsonData()moveToCenter()zoomToFit() 加载内联数据集并规范化视口。

图本身被配置为一棵从左到右的树,参数包括 layoutName: 'tree'from: 'left'treeNodeGapH: 120treeNodeGapV: 10。默认节点是矩形的 100x30 块,连线使用 RGLineShape.StandardCurve,连接点使用 RGJunctionPoint.lr,展开按钮位置设置在右侧。

最重要的选项是 fullscreenElementXPath: '#my-fullscreen-content'。它告诉 relation-graph 的内置全屏操作应当以外层包装元素为目标,而不是仅针对图元素本身,因此页头和两侧面板会与图一起进入全屏。

这个示例没有使用自定义 slots、编辑 API 或自定义工具栏逻辑。本地 SCSS 文件也只包含空的选择器骨架,因此最终可见效果主要来自图配置和外围的 flex 布局,而不是大量样式覆盖。

关键交互

  • 点击内置工具栏中的全屏按钮后,整个 #my-fullscreen-content 外层容器会进入全屏,因此页头和两侧面板会与图一起保持可见。
  • 点击节点会触发 onNodeClick 并记录节点文本。它不会改变渲染出的 UI,因此节点检查并不是这个示例的重点,全屏行为才是。

关键代码片段

这个外层结构说明,整个 demo 都运行在同一个 relation-graph provider 上下文中。

const Demo = () => {
    return (
        <RGProvider>
            <MyGraph />
        </RGProvider>
    );
};

这个选项块证明,图本身保持了简单配置,而全屏则被重定向到一个更大的 DOM 容器。

const graphOptions: RGOptions = {
    layout: {
        layoutName: 'tree',
        from: 'left',
        treeNodeGapH: 120,
        treeNodeGapV: 10
    },
    fullscreenElementXPath: '#my-fullscreen-content',
    debug: false
};

这个片段展示了该示例如何以内联方式构建由扁平 nodes 和 lines 组成的 RGJsonData

const myJsonData: RGJsonData = {
    rootId: 'a',
    nodes: [
        { id: 'a', text: 'a' },
        { id: 'b', text: 'b' },
        { id: 'b1', text: 'b1' }
    ],
    lines: [
        { from: 'a', to: 'b' },
        { from: 'b', to: 'b1' }
    ]
};

这一步预处理会在数据集加载前补齐缺失的 line id。

myJsonData.lines.forEach((line, index) => {
    if (!line.id) {
        line.id = `line-${index}`;
    }
});

这段初始化流程展示了在数据对象准备完成之后,图实例的完整工作流。

await graphInstance.setJsonData(myJsonData);
graphInstance.moveToCenter();
graphInstance.zoomToFit();

这段布局片段说明,全屏目标是一个包含说明内容和侧边面板的页面级外层容器,而不只是 RelationGraph 组件本身。

<div className="my-graph bg-white" id="my-fullscreen-content">
    <div className="flex flex-col" style={{ height: '100vh' }}>
        <div className="border-b">
            <div className="p-4 text-xs">
                <div className="font-bold text-sm">Customize the fullscreen display content using the fullscreenElementXPath option.</div>
            </div>
        </div>
        <div className="grow flex">
            <div className="bg-pink-200 w-36 shrink-0 flex place-items-center justify-center border-r border-gray-300">Left</div>
            <RelationGraph options={graphOptions} onNodeClick={onNodeClick} />
            <div className="bg-blue-200 w-36  shrink-0 flex place-items-center justify-center border-l border-gray-300">Right</div>
        </div>
    </div>
</div>

这个示例的独特之处

对比数据清楚地说明了它的核心差异:这个示例的重点并不主要在树布局、命令式图控制或 slot 放置上。它最独特的启示是,relation-graph 的全屏可以被重定向到外层容器,因此周围的页面内容仍然能成为全屏体验的一部分。

graph-instance-api 相比,它使用了非常相似的 provider 与实例配合方式,也采用了相近的树形骨架,但在加载完成后对图状态的操作要少得多。与 adv-hide-2-show 相比,它关注的不是隐藏容器中的延迟挂载。与 built-in-slots 相比,这里的辅助 UI 是位于 RelationGraph 外部、普通的页面级同级 DOM,而不是注入到图自身 view 或 canvas 层中的 HTML。

这种由朴素三栏外层结构、小型从左到右树形图以及 fullscreenElementXPath 组成的组合,使这个示例更适合作为以下需求的起点:“我的图位于一个更大的页面中,而全屏时也应该包含这个更大的页面。”

这种模式还适用于哪里

这种模式很适合迁移到以下场景:带持久图例的架构查看器、带证据侧边栏的案件审查页面、带摘要面板的组织树页面,以及带页头说明或筛选器的监控仪表板。在这些迁移场景中,图本身可以继续保持技术上简单,而全屏行为仍然尊重周围布局。

它也适用于需要在图旁边放置说明文字的文档和引导页面。可复用的思路是选择一个包含所有需要在全屏后继续可见的 UI 元素的外层容器,然后将 fullscreenElementXPath 指向这个容器。