# 前端可视化库设计草案 (@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` 给它的快照。 * 例如:`` ## 3. 库的形态设计 (API Preview) 如果这个库被开发出来,它在前端项目中的使用方式可能如下(以 React 为例): ```typescript 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 (
{/* 播放控制栏 */} {/* 渲染区域:根据 snapshot 中的数据自动渲染 */}
{snapshot.tracers.map(tracer => { if (tracer.type === 'array') { return } if (tracer.type === 'graph') { return } })}
); } ``` ## 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 树布局