Files
llm-wiki/docs/spark/2026-06-26-global-sigma-zoom-controls-design.md
2026-07-12 21:26:08 +08:00

9.4 KiB

全局 Sigma 图谱平滑缩放与左下缩放按钮设计

日期:2026-06-26 分支:codex/fix-global-graph-zoom-controls 关联:GitHub issue #73

背景

当前工作台图谱有两套视图:

  • 全局视图使用 Sigma/Graphology。
  • 社区视图使用现有 DOM 图谱相机。

用户反馈集中在全局视图:滚轮和触控板缩放太快,轻轻一滑就突然变大或变小;继续缩小还可能让节点小到几乎消失。社区视图的缩放手感相对舒服,原因是它按真实滚轮距离连续计算缩放,并且有缩放边界。

这次 issue #73 提供的是重要线索,不作为唯一方案来源。结合当前代码后,推荐方案是:工作台全局 Sigma 图谱继续支持滚轮/触控板缩放,但不再使用 Sigma 默认的“按事件方向跳档”的滚轮手感;改为项目自己的连续缩放逻辑,并新增左下独立的放大/缩小按钮。

目标

  1. 全局图谱滚轮/触控板缩放变得平顺、可控,接近社区视图现有手感。
  2. 全局图谱不再因为轻微滑动突然变很大或很小。
  3. 全局图谱缩放有合理上下限,避免无限放大或无限缩小。
  4. 全局图谱左下增加独立的 + / - 缩放按钮。
  5. 滚轮、触控板、按钮使用同一套缩放规则,不出现三种不同手感。

不做

  1. 不改离线 HTML 的完整体验;本次只保证共享代码改动不主动破坏离线入口。
  2. 不改社区视图的缩放体验。
  3. 不改图谱数据、选择、搜索、筛选、Pin、社区高亮、右抽屉等功能语义。
  4. 不引入新的图谱库或新的 npm 依赖。
  5. 不修改 node_modules/

用户体验定义

1. 滚轮和触控板仍然可以缩放

全局图谱保留滚轮/触控板缩放。改变的是缩放计算方式,不是取消滚轮缩放。

2. 缩放必须连续

触控板轻滑一点,只缩放一点;滑动距离更大,缩放幅度才更大。

当前 Sigma 默认滚轮逻辑主要看滚轮方向,一次事件就是固定倍率跳档。这个模型会让高频小 delta 的触控板变成连续猛跳。新设计要改为按真实 deltaY 计算缩放倍率。

参考社区视图现有逻辑:

  • 先把 wheel delta 标准化为像素距离。
  • 再用指数曲线把 delta 映射成缩放倍率。
  • 单次缩放倍率做防甩动限制。

全局 Sigma 视图采用同一类规则:

nextRatio = currentRatio * exp(normalizedDeltaY * WHEEL_ZOOM_SPEED)

说明:

  • 社区视图的 scale 越大表示越放大。
  • Sigma 的 ratio 越小表示越放大。
  • 所以全局 Sigma 用 exp(+deltaY * speed),与社区视图的 scale * exp(-deltaY * speed) 在手感方向上对应。
  • WHEEL_ZOOM_SPEED 使用社区视图当前舒服的值:0.0016。只有浏览器实测证明全局 Sigma 与社区视图仍有明显偏差时,才允许带测试记录调整这个常量;不能回到按事件跳档。

3. 缩放必须稳定

滚轮/触控板缩放时,以鼠标所在点为缩放锚点。用户指着哪里缩放,哪里就尽量留在原地。

按钮缩放时,以当前画面中心为缩放锚点。点击 +- 不应该让画面突然飞到别处。

4. 缩放必须有边界

全局 Sigma 相机要设置 minCameraRatiomaxCameraRatio,并且项目自己的缩放逻辑也要遵守同一边界。

边界目标:

  • 最大放大:能看清局部节点,但不把节点放到失控巨大。
  • 最大缩小:能退回全局关系,但不让节点小到消失。

实现初始值:

  • 放大下限:minCameraRatio = 0.3
  • 缩小上限:maxCameraRatio = 3

如果视觉验证发现这两个值仍然让节点过大或过小,必须用新的浏览器验证结果说明为什么调整,并同步更新测试预期。无验证记录时,不继续调参。

5. 滚轮缩放不能积压动画

滚轮/触控板缩放应该即时响应,不排队播放动画。用户停止滚动后,画面也应很快停下,不能继续追一串旧动画。

因此:

  • 滚轮/触控板缩放直接更新相机状态。
  • 按钮缩放可以有短动画,但下一次点击必须接管上一次动画目标。

6. 按钮步长要明确但不猛

左下缩放按钮是地图导航控件,不是精细触控板替代品。

按钮点击一次使用中等固定步长:

  • +:放大一档,ratio 乘以 1 / 1.18
  • -:缩小一档,ratio 乘以 1.18

这个步长比触控板轻滑更明确,但不能像当前全局滚轮那样猛跳。

交互布局

新增一个独立的左下缩放控件:

  • 位置:全局图谱画布左下角。
  • 内容:竖向排列 +-
  • 样式:沿用现有图谱工具条的半透明纸面风格,但作为单独控件存在。
  • 与现有工具条关系:不放进顶部“筛选 / 图例 / 回全图”工具条。
  • 与“回全图”关系:+ / - 只缩放;“回全图”继续负责回到全局构图。

控件区域本身要阻止画布滚轮缩放和点击穿透,避免用户在按钮附近滚动时误操作图谱。

架构设计

1. 缩放控制归属

缩放控制放在共享图谱引擎的 Sigma 全局渲染路径中,而不是放在工作台 React 外壳里。

理由:

  • 当前全局图谱相机由 packages/graph-engine/src/render/sigma-global-renderer.ts 管理。
  • Sigma 的鼠标事件、相机状态、锚点缩放都在这一层更容易正确处理。
  • 工作台外壳不应该理解 Sigma 相机细节。

2. Sigma 默认滚轮处理

Sigma 的 mouse captor 会先发出 wheel 事件,再执行默认缩放。项目应监听这个 wheel 事件并调用 preventSigmaDefault(),阻止 Sigma 默认跳档缩放,然后执行项目自己的连续缩放。

需要使用的 Sigma 能力:

  • getMouseCaptor().on("wheel", handler):接管滚轮事件。
  • wheel payload 的 original.deltaY / original.deltaMode:读取真实滚轮输入。
  • getCamera().getState():读取当前相机。
  • getViewportZoomedState(pointer, nextRatio):按鼠标位置计算新相机状态。
  • getCamera().setState(nextState):即时更新滚轮缩放。

如果某个运行环境缺少上述能力,必须降级为保守的 Sigma 参数方案,而不是让全局缩放不可用。

3. 缩放按钮

createGraphToolbar 不承载缩放按钮。新增一个独立的 Sigma 缩放控件创建函数,挂载到 Sigma 全局 route shell 内。

控件通过 renderer 暴露的缩放方法驱动相机,例如:

  • zoomIn()
  • zoomOut()

按钮缩放使用当前 Sigma 容器中心点作为锚点,计算方式与滚轮一致,只是输入为固定倍率。

4. 与现有高亮相机动画的关系

当前 main 已经有全局社区高亮与轻微相机构图动画。缩放改动必须与它共存:

  • 选中社区后仍允许现有轻微构图。
  • 用户滚轮/按钮缩放后,以用户缩放后的相机为准。
  • 滚轮缩放不触发社区选择或清空选择。
  • “回全图”仍然可以回到全局构图。

错误与降级

  1. 如果无法读取真实 wheel delta,使用 Sigma wheel payload 的 delta 做保守计算,但仍要避免默认 1.7 跳档。
  2. 如果无法使用 getViewportZoomedState,按钮和滚轮都不应让画面飞走;可以退化为以当前相机中心缩放。
  3. 如果 Sigma runtime 不支持 mouse captor,则至少设置较温和的 zoomingRatio 与相机上下限,保证不出现无限缩放。
  4. 所有异常通过现有 onFatalError 路径上报,不让整张图谱黑屏。

测试计划

单元测试

  1. sigma-global-renderer.test.ts

    • 创建 Sigma 时包含合理的相机边界。
    • wheel handler 会阻止 Sigma 默认缩放。
    • deltaY 只产生小幅缩放,大 deltaY 产生更明显缩放。
    • 连续 wheel 不排队动画,使用即时相机更新。
    • wheel 缩放使用鼠标位置作为锚点。
    • zoomIn / zoomOut 使用同一套缩放计算与相机边界。
  2. renderer-boundary.test.ts

    • 左下缩放控件存在。
    • + / - 点击分别触发放大/缩小回调。
    • 控件点击不穿透到图谱选择。
  3. gestures.test.ts 或等价覆盖

    • 滚轮经过缩放控件时不触发图谱缩放。

浏览器验证

  1. 启动工作台,进入全局图谱。
  2. 使用触控板轻滑:图谱只轻微缩放,不猛跳。
  3. 连续滚动后松手:画面快速停止,不继续追动画。
  4. 鼠标停在节点附近滚轮缩放:该区域保持稳定,不飞跑。
  5. 多次缩小:节点仍可见,不能缩到消失。
  6. 多次放大:节点不会失控巨大。
  7. 点击左下 + / -:画面按中等步长缩放,且以画面中心为基准。
  8. 选中社区后再缩放:高亮仍在,缩放正常。
  9. 回全图仍按原语义工作。

回归检查

  • npm run test -w @llm-wiki/graph-engine
  • 受影响情况下运行 Sigma 全局浏览器验证脚本。
  • 若改动 CSS 或控件布局,打开工作台实际查看浅色/深色下左下按钮是否清晰、不遮挡主要图谱内容。

完成标准

这个任务实现完成时,必须同时满足:

  1. 工作台全局图谱滚轮/触控板缩放手感接近社区视图,不再轻滑猛跳。
  2. 工作台全局图谱缩放有上下限,不会无限缩小或无限放大。
  3. 工作台全局图谱左下有独立 + / - 缩放按钮。
  4. 按钮和滚轮使用同一套缩放规则。
  5. 现有全局社区高亮、搜索、筛选、Pin、回全图没有被破坏。
  6. 单元测试和浏览器验证通过。