# Vs Story

> 使用 Three.js 与 Anime.js 将复杂概念、流程或系统制作成对象驱动的滚动叙事网页。适用于知识解释、系统机制、历史过程、数据流、产品原理和因果链可视化。重点不是给文章添加动画，而是让对象、关系和状态随滚动真实变化，使用户主要通过视觉理解内容。Use whenever the user wants to build a scroll-driven explanatory webpage, a scrollytelling page, a 3D interactive explainer, a process/flow/system visualization that changes as you scroll, or turns a concept/mechanism into an animated object-based story.

- Skill: `zeroz-lab/vs-story` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add zeroz-lab/vs-story`
- Raw SKILL.md: https://api.skillmd.com/api/skills/zeroz-lab/vs-story/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: zeroz-lab (https://skillmd.com/u/zeroz-lab)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/zeroz-lab/vs-story

---


# Visual Scrollytelling

## 目标

根据用户提供的主题，生成一个可直接运行、响应式、可回退的滚动叙事网页。

技术栈固定为：

* Three.js：场景、对象、材质、空间关系、摄像机和渲染。
* Anime.js：统一动画时间轴、对象状态插值、转场和滚动进度映射。
* 原生 HTML、CSS、JavaScript：内容结构、滚动检测、无障碍和响应式布局。

不得改用 GSAP、ScrollTrigger、React、Vue、Framer Motion 或其他动画、三维框架，除非用户明确修改技术约束。

## 核心原则

滚动叙事不是“文字随滚动出现”，而是让一个对象、过程或系统随着滚动真实运行。

视觉必须承担主要解释职责，文字只负责标题、短标签、条件和结论校准。

设计完成后，即使隐藏主要说明文字，用户仍应大致理解：

1. 画面中有哪些关键对象；
2. 当前发生了什么变化；
3. 为什么会产生这一变化；
4. 变化如何影响下一阶段；
5. 整个过程如何结束。

## 协作式设计流程（默认）

视觉取舍会显著改变结果，默认分阶段交给用户选择。只有用户明确说“你决定”“直接做”“不要询问”时，才自主完成全部决策；用户也可以只授权某一个决策门。

进入全权委托分支时，内部完成四项选择，向用户展示一份简短决策记录作为知情说明，并继续完成用户要求的交付物，不把记录变成审批点。

开始时从主题中提取学习目标、核心对象、参与者、状态变化、因果关系、反馈机制和终止条件。普通技术细节可合理假设，叙事、审美、构图和体验方向必须进入决策门。

### 决策门规则

每次只处理当前阶段，一次只呈现一个决策门：

1. 提供 2—3 套彼此完整、明显不同的方案，每套都以一致组合呈现；
2. 推荐项排第一，说明推荐理由、用户会看到的效果、主要取舍和实现影响；
3. 要求用户明确选择，也允许“选 A，但修改一个维度”；
4. 记录已锁定的选择，后续方案必须服从；修改已锁定选择时先说明影响；
5. 用户选择后才进入下一阶段。等待期间以当前方案说明为完成边界。

统一使用简短格式：

```text
决策 2/4：视觉方向
A（推荐）— 预期效果；主要取舍
B — 预期效果；主要取舍
C — 预期效果；主要取舍
请选择 A/B/C，或指定要调整的一个维度。
```

### 决策 1：叙事模型

编码前提供 2—3 套章节结构。每套明确学习目标、贯穿对象、关键事件、反馈方式和结束状态。用户选定后，输出简短决策记录。

### 决策 2：视觉方向

读取 `references/design-layers.md`，形成 2—3 套一致的设计包。每套同时包含画面形式、主要动作、时间结构、美术语言、三色调色板、镜头方式和文字空间关系。用户选定后锁定，后续设计保持同一方向。

### 决策 3：关键分镜

写 Three.js 场景前，先展示首屏、关键转折和终态的分镜方案。环境支持时给出静态概念图或可查看稿；否则使用清晰的文字线框。让用户确认对象造型、构图、镜头和文字位置。

### 决策 4：动态样段

先实现前 2—3 章作为 tracer prototype，提供可查看入口，让用户体验滚动节奏、信息密度、动画幅度和反馈是否清楚。确认后再扩展完整页面。

Three.js 对象复用、时间轴实现、像素比限制、resize、键盘导航、响应式、无障碍、reduced-motion 和 WebGL fallback 等工程细节由技能自主完成。

## 美术方向（必做，在写任何场景之前）

叙事结构清楚之后、写任何 Three.js 代码之前，必须先锁定一个具体的美术方向。没有美术方向的"对象/关系/状态"会退回到最通用、最像 AI 默认产物的长相（黑底 + 发光几何体 + 玻璃面板）。

### 第一步：选一个方向，并贯彻到底

从主题气质出发选一个方向，整页只能有一个。混合多个方向等于没有方向。可参考的方向（不限于）：

* 编辑极简（纸底、墨色、衬线大标题、大量留白、正交相机）；
* 电影夜景（近黑底、深青、一束暖光、体积雾、景深）；
* 有机生物（暖色渐变、柔体、膜、涟漪，无锐角无发光）；
* 技术档案 / 野兽派印刷（骨白、墨、一个专色、等宽字、暴露网格、双色丝网印刷质感）。

方向选定后，整页的材质、字体、相机、色板都必须服从它。不要在"电影夜景"里突然出现"编辑极简"的衬线面板。

### 第二步：定死调色板

整页最多 3 个颜色角色：底色、主色、一个强调色。强调色只承担一个语义（如"当前激活/建立"），不得用同一种颜色表达多个互相冲突的状态。在注释里写明每个 hex 和它的语义角色。过程不得临时新增颜色。

### 禁止的 AI 默认长相

下面这些是模型最常见的、让作品立刻显得"AI 味重"的默认产物，不得作为审美方向：

* 半透明毛玻璃面板（`backdrop-filter: blur`）堆叠当主要文字容器；
* 黑底 + 自发光几何体 + bloom，即 Three.js 入门教程的默认长相；
* 仪表盘 chrome：顶部细进度条、底部药丸状态标签、右上角浮动提示卡同时出现；
* 语义状态色（蓝/绿/橙/红/紫）全部上齐，像流程图配色；
* 对称居中的"两节点 + 中间连线"教科书构图，缺乏层次；
* 所有元素同时发光、同时高亮。

如果第一版看起来像上面任何一条，先换美术方向，不要靠调参数硬救。

## 叙事建模

将主题转化为四类视觉元素。

### 对象

表示系统中存在的实体。不同类别必须使用不同造型，不能全部设计为相似矩形卡片。

建议映射：

* 目标：晶体、胶囊、终点核心；
* 数据：粒子、卡片、数据包；
* 状态：仓库、容器、插槽、抽屉；
* 决策：分叉轨道、候选卡、筛选器；
* 工具：终端、雷达、机械设备；
* 外部环境：城市、网络、建筑或独立空间；
* 验证：天平、对比台、锁定装置；
* 失败：断裂、阻断、反弹或红色回流；
* 完成：闭合、稳定、锁定或持续点亮。

### 关系

通过空间、路径和运动表达：

* 包含；
* 输入与输出；
* 依赖；
* 控制；
* 分支；
* 反馈；
* 对比；
* 因果。

静态可能关系使用低透明度轨道；当前实际路径使用高亮轨道、方向箭头和运动数据包。不要同时高亮所有连线。

### 状态

对象至少应区分：

* 未出现；
* 未激活；
* 当前处理；
* 已选择；
* 执行中；
* 成功；
* 失败；
* 已淘汰；
* 已验证；
* 已完成。

状态变化不能只依靠文本替换，应通过物体位置、形态、连接、亮度、颜色或容器内容变化体现。

### 事件

优先使用具有机制含义的变化：

* 拆解；
* 组合；
* 插入；
* 移除；
* 展开；
* 筛选；
* 选择；
* 发送；
* 返回；
* 阻断；
* 回流；
* 比较；
* 锁定；
* 停止。

淡入、旋转、漂浮和发光只能作为辅助，不得成为主要叙事动作。

## 场景设计

使用一个持续存在的视觉舞台，不要为每章重新创建互不相关的画面。

核心对象必须贯穿始终，并在不同阶段发生结构或状态变化。

复杂度应逐步增加：

```text
核心对象
→ 出现第一个关系
→ 加入状态或容器
→ 展开候选路径
→ 连接外部环境
→ 出现反馈或失败
→ 修正并重新执行
→ 验证结果
→ 展示完整系统
```

第一屏不要一次展示全部模块和连线。

## 章节设计

每个章节只回答一个认知问题：

* 现在应该看什么；
* 发生了什么变化；
* 为什么发生；
* 变化后形成了什么新状态。

每章的局部时间轴建议划分为：

```text
0.00—0.15：镜头进入或对象聚焦
0.15—0.55：核心结构变化
0.55—0.80：保持稳定，供用户观察
0.80—1.00：准备进入下一阶段
```

关键变化后必须留出稳定观察区间，不要让画面始终运动。

至少包含一次由反馈引发的修正：

```text
执行原路径
→ 得到异常结果
→ 结果回写
→ 原方案失效
→ 新路径被选择
→ 再次执行
```

如果主题本身没有失败机制，可改为对比、筛选、排除或纠正错误假设。

## 镜头规则

摄像机是教学指针，不是装饰。

每章只能有一个主要视觉焦点：

* 当前对象：清晰、高亮、靠近镜头；
* 相关对象：保留但降低权重；
* 背景对象：降至约 10%—25% 的视觉强度。

镜头应根据叙事任务选择：

* 讲整体结构：拉远；
* 讲内部组成：靠近或进入容器；
* 讲对象流转：跟随运动对象；
* 讲选择：正面对准候选路径；
* 讲失败：停在阻断位置；
* 讲验证：使用便于比较的正面视角；
* 讲完成：重新拉远，呈现完整系统。

避免无目的的持续摇摆、环绕和大幅缩放。

## 文字规则

文字只保留：

* 阶段标题；
* 一句核心解释；
* 对象短标签；
* 必要约束；
* 新增或删除的状态差异；
* 最终结论。

禁止：

* 大段正文占据主要视觉区域；
* 左右两块固定文字面板同时争夺注意力；
* 重复描述画面已经表达的过程；
* 依赖大量英文标签才能区分对象；
* 用文字宣布一个画面没有证明的结论。

优先把说明贴近相关对象，而不是集中放入独立信息面板。

### 文字与画面的空间关系（必选一种，写任何章节文字之前先定）

这是最常见的构图固化陷阱：没有提前决定文字怎么放，结果每章都退回到"左边一个文字框、右边一个文字框"交替贴边的安全默认。连续几章这样排，整页会显得机械、模板化，画面也拿不到完整空间当主体。

在写任何章节文字之前，先从下面选一种空间关系，整页贯彻一种为主（可少量混用，但必须有主导模式）：

* **顶部标题带**：所有文字统一收在画面顶部一条窄带（序号 + 标题 + 一句话），画面占据下方主体。文字位置固定，章节切换时只换内容、不换位置。适合画面是绝对主角、文字只做点题的场景。
* **中央字幕层**：文字直接叠在画面中央，像电影章节卡，随滚动淡入淡出。画面始终在文字背后。适合电影感、氛围重的叙事。
* **引线注释**：文字是从画面里某个对象拉出的一根细线 + 短注释，紧贴它解释的那个对象，位置随该对象移动。适合需要精确指认局部机制的图解。
* **画面优先纯镜**：大部分章节没有独立文字，画面独自承担叙事，只在关键转折处出现一行标题或结论。适合对象本身表现力强、机制一目了然的题材。

不论选哪种，都不得出现"每章交替地在左侧、右侧贴一个独立文字框"的模板化排版。如果发现连续两章以上的文字位置只是左右镜像，停下来重新选空间关系，而不是继续复制框。

移动端可以简化（例如引线注释退化为顶部短标签），但主导模式不能丢。

## 视觉语法

为整个页面建立稳定的语义，过程中不得随意改变。

语义角色是固定的（成功/完成、失败/阻断、未激活/可能、信息、执行等），但具体用什么颜色表达，必须来自美术方向里定死的 3 色调色板——不要为了凑齐所有语义而铺开一整套彩虹色板。

把语义映射到调色板，而不是反过来。典型做法：

* 强调色（唯一）→ 当前选中、成功、完成、建立；
* 主色 → 信息、数据、只读、执行；
* 次级/降权色（主色的低透明度或灰）→ 未激活、可能路径、失败/阻断。

当多个语义需要区分、但调色板颜色不够时，优先用**形态、位置、明度、纹理**区分，而不是新增颜色。一种颜色不要承担多个互相冲突的含义。

## 技术实现

页面使用单一 Three.js 渲染循环。

滚动处理分为两层：

1. 章节状态：使用 IntersectionObserver 或元素视口位置判断当前章节；
2. 章节进度：计算当前章节内部的 `0—1` 局部进度。

全局滚动百分比只能用于页面总进度条，不得直接控制全部叙事动画。

将局部滚动进度映射到 Anime.js 时间轴：

```text
section local progress
→ Anime.js timeline seek
→ Three.js 对象状态
→ Three.js render
```

所有核心变化必须能够由时间轴进度推导，确保用户向上滚动时可以自然恢复旧状态。

避免只执行一次、无法反转的命令式动画。

## 性能要求

* `devicePixelRatio` 最大限制为 2；
* 避免实时阴影和高成本后处理；
* 复用几何体和材质；
* 避免在渲染循环中创建新对象；
* 控制透明材质和粒子数量；
* DOM 不得在每帧进行大规模更新；
* resize 后重新计算摄像机、渲染尺寸和章节位置；
* 页面滚动过程中保持视觉、文字和状态同步。

## 响应式与降级

桌面端可以展示空间关系和多对象协作。

移动端不能只是缩小桌面版，应改为：

* 每阶段只保留核心对象；
* 隐藏次要连线和背景结构；
* 缩短镜头移动；
* 减少粒子与透明材质；
* 将状态说明改为短标签；
* 避免固定面板遮挡主体。

必须支持 `prefers-reduced-motion`：

* 固定摄像机；
* 取消大幅移动、环绕和连续缩放；
* 使用状态切换和轻度淡入替代；
* 保留完整信息和章节顺序。

WebGL 不可用时，显示清楚的静态后备说明，不得留下空白页面。

## 禁止事项

* 不要把所有内容做成发光矩形卡片；
* 不要把 Three.js 当成动态背景；
* 不要用大量文字弥补对象设计不清晰；
* 不要让所有对象始终同时高亮；
* 不要让连线缺少方向和当前状态；
* 不要用粒子、光晕和旋转掩盖机制不清楚；
* 不要使用通用 SaaS Hero、Features、Stats、CTA 结构；
* 不要制造没有依据的数据、结果或指标；
* 不要引入与 Three.js、Anime.js 角色重复的第三方框架。

## 输出要求

默认交付一个完整、可直接保存运行的 HTML 文件，包含：

* HTML 结构；
* 响应式 CSS；
* Three.js 场景；
* Anime.js 时间轴；
* 滚动进度映射；
* 键盘上下章节导航；
* reduced-motion 降级；
* WebGL 错误处理；
* 必要代码注释。

如果项目复杂，可拆分为：

```text
index.html
styles.css
main.js
scene.js
timeline.js
content.js
```

但必须保证入口清晰、无需补写核心代码即可运行。

## 验证

交付前依次检查：

### 结构检查

* 是否存在贯穿全程的核心对象；
* 不同概念是否具有不同造型；
* 系统内部与外部边界是否清楚；
* 当前路径与潜在路径是否可区分。

### 美术检查

* 是否在写场景前就锁定了一个具体美术方向，并贯彻到底；
* 调色板是否不超过 3 个颜色角色，且每个 hex 的语义在注释里写明；
* 是否避开了"AI 默认长相"清单（玻璃面板、黑底自发光、仪表盘 chrome、全语义彩虹色板）；
* 换掉美术方向能否解决，而不是靠调参数硬救。

### 叙事检查

* 每章是否只有一个主要焦点；
* 每次滚动是否带来一个有意义的变化；
* 前后阶段是否存在明确因果；
* 关键变化后是否有观察停顿；
* 向上滚动是否可以恢复状态。

### 构图检查

* 是否在写章节文字前就选定了一种文字-画面空间关系，并贯穿整页；
* 是否出现了"每章左右交替贴一个独立文字框"的模板化排版——出现就重做。

### 无文字测试

隐藏长说明后，仅看物体、路径和短标签，用户是否仍能复述主要过程。

### 静帧测试

在任何阶段暂停，是否能判断：

* 当前处理哪个对象；
* 系统处于什么状态；
* 刚刚发生了什么；
* 下一步可能发生什么。

### 技术检查

至少完成：

* HTML 结构检查；
* JavaScript 静态语法检查；
* 桌面尺寸检查；
* 移动尺寸检查；
* reduced-motion 检查；
* 浏览器滚动和反向滚动检查。

不得把静态检查描述为真实浏览器端到端验证。

## 完成标准

只有同时满足以下条件，任务才算完成：

1. 视觉对象而非长文字承担主要解释；
2. 用户始终知道当前应该看哪里；
3. 滚动可以前进，也可以恢复旧状态；
4. 动画表达机制变化，而不是单纯装饰；
5. 桌面、移动端和低动态模式均可理解；
6. 用户看完后能够复述完整过程及其因果关系。

先把知识转换成对象、关系、状态和事件，再用 Three.js 构建持续存在的视觉世界，用 Anime.js 将每个章节的局部滚动进度映射为可逆时间轴；文字只做标注，动画必须直接解释机制。

