小玩意-时钟
这个示例用一个中心节点、60 个生成的秒节点和一个独立移动标记节点,构建了一个自运行的时钟式径向图。它是计时驱动回放、选中态同步和自定义节点插槽渲染在只读 relation-graph 场景中的紧凑参考。
带移动标记节点的钟表式径向播放
这个示例构建了什么
这个示例把一个 relation-graph 转成了类似钟表的径向展示。一个较大的中心节点作为枢纽,六十个带编号的圆形节点构成外环,另一个独立的半透明标记节点每隔 500 ms 沿着各条辐条依次移动。
这个查看器没有暴露本地控制或编辑工具。它的主要行为是自动播放:图在挂载时自行加载,居中画布,缩放到适应视口,然后在六十个位置之间推进,同时让当前激活的辐条保持已选中的视觉状态。
最值得注意的细节是,这个动画并不是通过每一步都重建整张图来实现的。相反,代码会保持这些编号节点固定不动,只移动一个专用的标记节点,并在播放推进时更新中心节点的自定义数据。
数据是如何组织的
图数据是在 initializeGraph() 内部、setJsonData(...) 执行之前以内联方式组装的。初始数据集包含一个根节点,带有 width: 100、height: 100 和 data.percent = 0。随后一个循环会创建节点 1 到 60,并为每个编号节点添加一条从 root 指向它的连线,从而形成整张图的辐条结构。之后,代码会额外追加一个位于画布外位置的 current 节点,这样它就可以在播放过程中被独立移动。
这意味着该示例对稳定结构和变化中的运行时状态做了清晰分离。辐条节点和连线表示周期中的固定位置,而 current 节点以及根节点的 percent 字段则表示叠加在该结构之上的实时状态。
在真实应用中,这种形态同样可以表示时间槽、轮班轮转、机器周期检查点、引导式演练步骤,或者任何其他需要可见“当前位置”指示器的固定环形序列。
relation-graph 是如何使用的
index.tsx 用 RGProvider 包装整个 demo,而 MyGraph.tsx 通过 RGHooks.useGraphInstance() 基于 provider 作用域内的实例 API 完全驱动这张图。示例从 relation-graph 的 center 布局开始,使用较低的弹性和斥力值,并设置 maxLayoutTimes: 3000,这足以在周期后续仍保留一小段自动布局阶段的同时,让径向排列保持可读。
图选项还定义了基础视觉样式:直线、路径上的线文本、默认 40x40 节点、无内置节点边框、白色节点背景,以及半透明灰色连线。真正可见的样式则由 RGSlotOnNode 提供,它渲染了三种不同的节点主体:渐变的 current 标记节点、一个由 node.data.percent 驱动填充量表的较大根节点,以及普通的编号秒节点,它们带有细灰色边框。
运行时真正完成工作的则是实例 API。setJsonData(...)、moveToCenter() 和 zoomToFit() 建立初始视图。startAutoLayout() 在第 15 秒开始一小段布局阶段,stopAutoLayout() 和 doLayout() 在第 60 秒重置场景,updateNodeData(...) 改变根节点量表,updateNodePosition(...) 移动标记节点,而 updateOptions(...) 保存当前秒数应被高亮的已选中节点和已选中连线。dataUpdated() 会在每个播放步进时刷新这些变更。
导入的 SCSS 文件会在 .my-graph 包裹器下为 checked-line 和 node-text 添加覆盖样式。审阅过的 JSX 本身并没有渲染这个包裹器,因此这些样式覆盖只有在外层宿主提供了匹配容器时才会生效。
关键交互
这是一个被动查看型 demo,而不是一个手动交互配方。图会在挂载时自动初始化,因此主要体验是在没有用户输入的情况下观察预设状态不断推进。
最重要的运行时交互是每 500 ms 一次的播放 tick。每次 tick 时,代码都会查找当前激活的编号节点,把 current 标记节点移动到该节点坐标上,再通过 getLinks() 找到对应的连线 id,并同时更新 checkedNodeId 和 checkedLineId,让视觉重点跟随移动中的标记。
同一轮周期内部还包含两个阶段切换。在第 15 秒时,demo 启用自动布局;第 18 秒时,它再次缩放以适应视口;到了第 60 秒,它会重置中心量表、停止自动布局、重新执行一次布局、让画布重新居中,然后开始下一轮周期。
关键代码片段
下面这个片段展示了钟表盘面如何在图加载前于内存中生成。
const myJsonData: RGJsonData = {
rootId: 'root',
nodes: [{ id: 'root', text: '', width: 100, height: 100, data: { percent: 0 }, nodeShape: RGNodeShape.circle }],
lines: []
};
for (let i = 1; i < 61; i++) {
myJsonData.nodes.push({ id: i.toString(), text: i.toString(), nodeShape: RGNodeShape.circle });
myJsonData.lines.push({ id: `line-${i}`, from: 'root', to: i.toString(), text: '' });
}
myJsonData.nodes.push({ id: 'current', text: '', x: -20, y: -20, nodeShape: RGNodeShape.circle });
下面这个片段展示了 demo 如何先让图适应视图,然后立刻开始自动播放。
await graphInstance.setJsonData(myJsonData);
graphInstance.moveToCenter();
graphInstance.zoomToFit();
timer.current = setInterval(() => {
play();
}, 500);
下面这个片段证明了播放过程是由实例更新驱动的,而不是完整重新加载数据。
if (currentSecond.current <= 20 && rootNode) {
graphInstance.updateNodeData(rootNode, {
percent: currentSecond.current / 15
});
}
// ...
graphInstance.updateNodePosition(focusNode, targetNode.x, targetNode.y);
const targetLinkId = graphInstance.getLinks().find((l) => l.toNode.id === targetNode.id)?.line.id;
graphInstance.updateOptions({
checkedNodeId: 'current',
checkedLineId: targetLinkId
});
下面这个片段展示了一个节点插槽如何渲染三种不同的视觉角色。
{node.id === 'current' && (
<div style={{ opacity: 0.5, borderRadius: '50%', background: 'linear-gradient(to right, #00FFFF, #FF00FF)' }}>
{node.text}
</div>
)}
{node.id === 'root' && (
<div style={{ borderRadius: '50%', overflow: 'hidden', border: '#000000 solid 1px' }}>
<div style={{ height: `${percent * 100}%`, marginTop: `${(1 - percent) * 100}%` }} />
</div>
)}
这个示例的独特之处
对比数据表明,这个示例的不寻常之处不只是自动启动或使用 center 布局,而是在一个小型查看器里组合了几种更少见的技术。它会在代码中生成六十个辐条节点,在加载前追加一个专用的 current 标记节点,通过 updateNodePosition(...) 移动该标记,并通过 checkedNodeId 和 checkedLineId 保持视觉焦点同步。
与 multi-group 和 multi-group-3 相比,这个示例把 center 布局当作一个带动画的仪表表面,而不是用于展示互不相连的分组,或作为过渡到更通用布局变化的方式。与 force-sea-anemone 相比,它的运动是确定性的、按步骤推进的:不是让多个节点在不断变化的力学设置下持续重组,而是让一个标记沿固定的 60 步周期前进。与 expand-holder-slot 相比,这里的自定义渲染服务于被动播放和中心量表,而不是点击驱动的展开或收起控制。
它最强的差异化组合在于钟表式辐条数据集、通过插槽渲染的圆形节点家族、由 updateNodeData(...) 驱动的渐变中心填充,以及位于同一播放循环内部、由秒数门控的短暂自动布局阶段。因此,相比通用图探索,它更适合作为脚本化焦点跟踪的起点。
这种模式还能用在哪里
同样的模式也可以复用于需要在固定检查点之间轮播的无人值守看板,例如制造周期展示、自助终端倒计时、巡检或轮班轮转,或者需要一次高亮一个槽位的周期性监控视图。
它也很适合用于引导式展示图状态。产品不需要为每一帧都重建数据集,而是可以保持结构图稳定,只把一个标记节点移动到当前目标位置,并更新少量节点元数据来显示进度、容量或完成度。