- 新增品牌命名、商业化策略、SDK视觉噪音处理、可视化库设计和系统架构文档 - 更新开发规则,明确禁止主动修改项目源代码文件 - 所有文档均为中文编写,用于记录项目设计讨论和决策
4.4 KiB
4.4 KiB
前端可视化库设计草案 (@structrail/viz)
本文档描述了将平台前端渲染逻辑沉淀为独立可视化库的设计构想。
1. 项目定位
我们将“数据生成”(Tracer SDK)与“数据展示”(Visualization Lib)完全解耦,旨在沉淀一套标准化的、可嵌入的前端可视化引擎。
- Tracer SDK (后端/客户端):负责生成标准化的、语言无关的 JSON 指令流(Trace Protocol)。
- Visualization Lib (前端):负责解析指令流,重建数据状态,并提供交互式的可视化组件。
这套库不仅服务于 StructRail 平台,未来也可被嵌入到博客、电子书或教学文档中,成为算法可视化的基础设施。
2. 核心架构 (Architecture)
库的核心遵循 Player + Store + Renderer 的分层架构,本质上是一个支持时间旅行(Time Travel)的确定性状态机。
2.1 Player (播放器/控制器)
- 职责:负责解析 Tracer 生成的 JSON 指令流,控制播放进度(Frame/Step)。
- 功能:提供
play(),pause(),next(),prev(),seek(index)等 API。 - 特性:它不关心具体怎么画,只关心“当前是第几步”以及“播放速度”。
2.2 Store (状态仓库/沙盒)
- 职责:负责根据指令重构数据结构的状态。
- 机制:维护一个“影子内存”(Shadow Memory)。
- 当 Player 处于第 0 步时,Store 是空的。
- 当收到
ArrayTracer.create指令时,Store 里建立一个数组模型。 - 当收到
patch指令时,Store 更新对应数组的元素值。 - 当收到
pick指令时,Store 标记对应元素为“高亮状态”。
- 输出:它能在任何时间点,输出一份只读的、标准化的数据快照 (Snapshot) 给渲染层。
2.3 Renderer (渲染器/组件库)
- 职责:纯粹的 UI 展示层(View),遵循
f(state) => UI的原则。 - 实现:可以使用 React/Vue 组件,也可以是 Canvas/WebGL(针对大规模数据)。
- 特点:它完全不知道“指令”的存在,它只接收
Store给它的快照。- 例如:
<ArrayVisualizer data={[1, 2, 3]} highlights={[1]} />
- 例如:
3. 库的形态设计 (API Preview)
如果这个库被开发出来,它在前端项目中的使用方式可能如下(以 React 为例):
import { Player, ArrayVisualizer, GraphVisualizer } from '@structrail/viz';
// 1. 载入 Tracer 生成的 JSON 数据
const events = await fetch('algorithm-trace.json');
const player = new Player(events);
// 2. 绑定到 UI
function AlgorithmDemo() {
// 使用 player 的 hook 获取当前帧的数据快照
const snapshot = usePlayerSnapshot(player);
return (
<div>
{/* 播放控制栏 */}
<ControlBar player={player} />
{/* 渲染区域:根据 snapshot 中的数据自动渲染 */}
<div className="canvas">
{snapshot.tracers.map(tracer => {
if (tracer.type === 'array') {
return <ArrayVisualizer key={tracer.id} model={tracer} />
}
if (tracer.type === 'graph') {
return <GraphVisualizer key={tracer.id} model={tracer} />
}
})}
</div>
</div>
);
}
4. 关键技术挑战 (Technical Challenges)
4.1 增量计算与快照管理
- 问题:如果算法有 100 万步,不能每一步都存一个深拷贝的快照。
- 策略:使用类似 Git 的机制或 immer.js。Store 只记录关键帧(Keyframe)的快照,中间步骤通过重放指令(Replay)动态计算。
4.2 动画过渡 (Animation)
- 问题:当从“第 1 步”跳到“第 2 步”时,如果只是数据的突变(1 -> 2),体验很生硬。
- 策略:渲染层需要比较
PrevSnapshot和CurrentSnapshot(Diff)。- 如果发现数组 index 0 的元素位置变了,它应该生成一个移动动画。
- 这就是为什么我们的
patch/swap指令语义很重要,它们对应了不同的动画原语。
4.3 自动布局 (Auto-Layout)
- 问题:后端 Tracer 通常不包含坐标信息(除非我们以后添加坐标指令,但通常不建议耦合 UI 细节)。
- 策略:前端库需要内置强大的自动布局算法。
- Graph: Force-directed graph (力导向图)
- Tree: Reingold-Tilford 树布局