docs: 新增项目文档并更新开发规则
- 新增品牌命名、商业化策略、SDK视觉噪音处理、可视化库设计和系统架构文档 - 更新开发规则,明确禁止主动修改项目源代码文件 - 所有文档均为中文编写,用于记录项目设计讨论和决策
This commit is contained in:
91
.trae/documents/visualization-library-design.md
Normal file
91
.trae/documents/visualization-library-design.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# 前端可视化库设计草案 (@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 为例):
|
||||
|
||||
```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 (
|
||||
<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 树布局
|
||||
Reference in New Issue
Block a user