这个文件是后续章节绘图系统的技术和教学设计草稿,不进入学生版 PPT。
推荐采用“轻量自研 SVG/HTML 组件 + G6 图结构组件”的混合路线。
理由:数据结构课程里大量图不是“任意 graph visualization”,而是“教学过程图”。数组、表格、桶、指针、探测路径和排序过程需要像板书一样精准可控;强行塞进 G6 的 node-edge 数据模型,会增加无意义复杂度。G6 应该用在它真正擅长的树和图上。
G6 当前文档显示它是 graph visualization engine,提供 graph drawing、layout、analysis、interaction、animation 等能力,并且有节点、边、combo、shape、layout、behavior、plugin、theme、animation 等模块。文档列出多种布局,包括 dagre、circular、force、grid、compact tree、dendrogram、mindmap、radial 等,适合树和图章节。
D3 的优势是底层通用、表达力强,适合自定义坐标、transition、scale 和数据绑定;缺点是需要自己建立完整组件体系,教学图规模一大容易变成“每页手搓”。
Cytoscape.js 是成熟的 graph theory/network visualization library,有布局、选择器、样式表、图算法和动画;它更偏网络应用和图分析系统,不太适合作为课程所有示意图的统一视觉底座。
参考:
QMD 只负责声明“这里需要一个什么演示”,不直接写 SVG/HTML 细节。
示例:
或:
建议新增:
scripts/course-viz.jsscripts/course-viz-g6.jsstyles/course-viz.css其中:
course-viz.js:通用自研 SVG/HTML 组件,包含数组、表格、栈队列、排序、桶、指针、状态机。course-viz-g6.js:只封装 G6 相关树/图组件,不污染基础组件。course-viz.css:只放语义 token 和通用布局,不为每个具体页面单独写 CSS。每个组件暴露统一接口:
不要让每个组件自己发明按钮逻辑。按钮、状态栏、计算栏、说明栏统一由 shell 提供。
每个动画都抽象成 step 序列:
这样 Prev/Next/Run/Final/Reset 都只是在 step 上移动,不再由每个动画临时写散乱逻辑。
颜色要少,语义要固定:
--viz-ink: 主文字和边框,黑色。--viz-paper: 背景,白色。--viz-muted: 次要线条和标签。--viz-active: 当前步骤,蓝色。--viz-success: 命中或完成。--viz-warning: 冲突、待处理。--viz-danger: 错误、失败、删除。--viz-ghost: 已访问但不是当前。形状语义:
CSS 不按章节或具体图命名,尽量按用途命名。例如:
.viz-shell.viz-toolbar.viz-canvas.viz-calc.viz-note.viz-cell.viz-token.viz-edge.viz-pointer.viz-state-active.viz-state-success每个组件必须支持三种密度:
normal:默认课堂演示,一页一个核心图。compact:配合代码或文字讲解,小图但仍可读。dense:习题答案或多图对比,只用于静态或少量动画。每个组件必须支持容器自适应:
建议基础尺寸:
第一阶段必须完成:
ArrayView:一维数组、索引、比较顺序、当前元素、区间高亮。TableView:二维表、动态规划表、邻接矩阵、状态转移高亮。BucketTableView:哈希桶、链地址、开放寻址、探测顺序。LinkedListView:单链表、双链表、指针移动、插入删除。StackQueueView:栈、队列、循环队列、双端队列。SortBarsView:排序条形图、比较、交换、已排序区间。FormulaTraceView:计算式逐步展开,与图同步。第二阶段:
HeapArrayView:堆的数组视图。HeapTreeView:堆的树视图,可与数组联动。UnionFindView:森林、parent 数组、路径压缩。MemoryPointerView:对象、地址、引用、空指针。ComplexityCurveView:复杂度曲线、数量级对比。第一阶段:
TreeViewG6:普通树、二叉树、遍历、高亮路径。GraphViewG6:无向图/有向图、邻接关系、选边、访问状态。TraversalViewG6:BFS/DFS 队列或栈与图同步。ShortestPathViewG6:Dijkstra/Bellman-Ford 的 dist 表与图同步。MSTViewG6:Kruskal/Prim 的候选边、已选边、环检测。第二阶段:
DAGViewG6:拓扑排序、关键路径。NetworkFlowViewG6:容量、流量、残量网络。GraphAlgorithmCompareG6:同一图上的不同算法过程对比。G6 只作为树/图渲染引擎,课程层仍然用我们的 step 状态机控制动画。不要把教学逻辑写进 G6 配置里。
后续要先做一个 visual-templates.qmd,作为全课程绘图质量基准。至少包含:
每个模板必须同时验证:
Prev/Next/Run/Final/Reset。scripts/course-viz.js 和 styles/course-viz.css,先抽出已有哈希章节中可复用的 shell、bucket、token、arrow、formula、step runner。chapters/00-visual-templates.qmd,只做模板页,不作为正式课程章节。chapter-production-guidelines.md 中作为后续章节规则。hash-demo.js 为全课程大杂烩。course-viz,哈希章节逐步迁移到新组件。chapters/00-visual-templates.qmd,作为标准组件模板页。scripts/course-viz.js,不覆盖原有 hash-demo.js。styles/course-viz.css,使用语义化 .viz-* class,避免继续按单页写 CSS。scripts/course-viz-include.html,当前通过 CDN 加载 G2、G6、S2、X6;后续定稿后应 vendored 到本地资源。https://unpkg.com/@antv/g2/dist/g2.min.js,X6 使用 https://unpkg.com/@antv/x6/dist/x6.min.js。最终分发前仍应 vendored 到本地。bucket X 文本,也不再用左侧箭头格。10 -> 17 -> 31,再画 24.next -> 31,再画 17.next -> 24,最后合并为 10 -> 17 -> 24 -> 31。24.next -> 31 建立后,旧的 17.next -> 31 仍然是实线;只有执行 17.next = 24 后旧边才消失。A, Z, C, W, D, X, Y,按字典序插入并逐步展示 RL、LL、RR、LR 旋转过程;不能再使用抽象的 x/y/z 瞎转示意。h_0(key) / h_1(key) 候选箭头、DFS 搜索满桶、cuckoo path、kick 过程和删除只检查两个候选桶。h_0(·) 与 h_1(·) 表示两个哈希函数,不展开具体算式。24;被访问到的 17、6 是路径上的旧 key,不应切换成“当前 key”。已经处于某个候选函数位置的旧 key,要把原函数标灰,把另一个函数标为当前候选,例如 17 从 h₀ 位置被踢出后探测 h₁(17),6 从 h₁ 位置被踢出后返回 h₀(6)。dist / prev / settled,本轮更新的单元使用浅绿色。Prev/Next;只有按 Ctrl/Meta 加方向键时才跳过动画、直接交给 reveal 翻页。该行为由 scripts/course-keyboard.js 安装,脚本必须单例保护,避免全局 include 和章节 include 重复加载时重复绑定。chapters/00-visual-templates.qmd 渲染后,页面中所有 data-viz 必须全部生成 viz-shell 和 viz-antv-canvas,且不能出现 Unknown viz 或 SyntaxError。