Files
SpineParticlesWeb/Document/网页粒子系统阶段九.md
T
2026-09-02 10:45:10 +08:00

14 KiB
Raw Blame History

网页粒子系统 · 阶段九

阶段定位:撤回与快捷键、编辑器配置持久化、可复用预设体系定版
完成日期:2026-08-30
工程目录:/Users/tianmokeji/Desktop/SpineParticle
技术栈:Vue 3 + TypeScript + Pinia + PixiJS 7 + Spine Runtime 4.2 + Vite


一、阶段结论

阶段九在阶段八场景编辑、Spine 骨骼跟随和对象复制能力的基础上,补齐了编辑器日常使用所需的撤回、快捷键、工程保存、工程加载和预设加载流程。

编辑器现在可以把粒子系统、碰撞体、路径、Spine、系统设置、画布视图和动画归属等数据保存为可移植 JSON,并能把 Spine 骨架、Atlas 与多张纹理一并内嵌。配置重新加载后不需要再次选择 Spine 原始文件,画布、动画列表和骨骼树可以直接恢复。

本阶段主要完成:

  1. 实现默认 20 步、最大 200 步的撤回历史;
  2. 在系统设置中增加最大撤回次数设置;
  3. 支持 Ctrl/Cmd + Z 撤回;
  4. 增加画布工具、时间轴和保存配置快捷键;
  5. 实现完整编辑器配置 JSON 下载保存;
  6. 实现本地 JSON 配置加载和数据恢复;
  7. 将 Spine 原始资源以内嵌 Data URL 形式纳入配置;
  8. 修复 Spine 配置恢复后的运行时资源注册和渲染;
  9. 实现 public/Preset/ 预设目录与自动索引;
  10. 实现预设列表、空状态和一键加载;
  11. 建立纯粒子、路径、碰撞体、Spine 和空场景测试预设;
  12. 修复包含 + 的预设文件名无法通过开发服务器读取的问题;
  13. 为预设加载错误增加文件命名检查提示;
  14. 修复同一配置第二次加载后停在第 0 帧的问题;
  15. 完成普通配置和含 Spine 配置的保存—加载往返验证。

二、撤回功能

2.1 历史模型

编辑器通过快照记录可撤回数据。默认保留 20 步,用户可以在系统设置中修改,允许范围为 1~200 步。

快照覆盖:

  • 全部粒子系统及其面板参数;
  • 全部碰撞体;
  • 全部路径与路径点;
  • 全部 Spine 场景对象;
  • 所属动画列表;
  • 除撤回上限自身以外的系统设置;
  • 对象显隐、背景图数据及背景偏移和透明度。

以下内容不作为普通撤回快照保存:

  • 粒子逐帧录制缓存;
  • PixiJS Texture 实例;
  • 拖尾运行时纹理实例;
  • 当前时间轴帧和正在播放状态;
  • 撤回上限本身。

这些数据属于运行时缓存或撤回系统自身配置,恢复快照后由编辑器重新计算或重建。

2.2 操作合并

参数连续拖动或连续输入不会为每个微小变化创建独立历史。编辑器在最后一次变化后等待约 250ms,再把连续变化合并为一步操作。

该设计适用于:

  • 滑块拖动;
  • 数值连续输入;
  • 曲线调整;
  • 场景对象变换;
  • 背景图偏移和透明度调整。

2.3 Spine 资源安全

Spine 场景对象的可序列化属性保存在快照中,已解析的 SkeletonData 和纹理通过资源注册表引用计数保留。

撤回删除、复制或资源替换操作时:

  • 快照仍引用的 Spine 资源不会被提前销毁;
  • 恢复快照时重新注册对应 Spine ID 的运行时资源;
  • 超出撤回上限的旧快照会释放自己持有的资源引用;
  • 粒子录制缓存清空并重新生成。

2.4 撤回后的状态修复

执行撤回后会:

  1. 恢复场景对象和设置;
  2. 修复当前选择,避免选择已不存在的对象;
  3. 恢复粒子系统所属动画;
  4. 清空旧录制帧;
  5. 重新计算时间轴总长度;
  6. 更新撤回按钮的剩余步数和可用状态。

当前阶段只实现“撤回”,尚未实现“重做”。


三、快捷键

3.1 快捷键表

快捷键 作用 生效范围
Ctrl/Cmd + Z 撤回上一步 全局
Ctrl/Cmd + S 下载保存当前编辑器配置 全局
Q 切换为画布拖动模式 画布已选中
W 切换位移工具 画布已选中
E 切换旋转工具 画布已选中
R 切换缩放工具 画布已选中
D 播放/暂停时间轴 全局非输入状态
S 回到时间轴第 0 帧 全局非输入状态

3.2 浏览器快捷键覆盖

Ctrl/Cmd + SCtrl/Cmd + Z 会阻止浏览器默认行为,分别交给编辑器保存和撤回,不再弹出浏览器网页保存或执行浏览器输入历史撤销。

3.3 输入控件保护

当焦点位于以下控件时,普通字母快捷键不会触发:

  • input
  • textarea
  • select
  • contenteditable 内容。

因此输入名称、搜索骨骼或编辑参数时,可以正常键入 q/w/e/r/d/s。带 Ctrl/Cmd 的保存与撤回仍按编辑器全局快捷键处理。


四、编辑器配置保存

4.1 保存入口

场景对象面板上方增加:

  • 保存配置
  • 加载配置
  • 选择预设

点击“保存配置”或按 Ctrl/Cmd + S,浏览器会下载:

SpineParticle-YYYYMMDD-HHMMSS.json

4.2 文件格式

当前格式标识与版本:

format: SpineParticle.EditorConfig
version: 1

顶层数据结构:

editor      画布缩放与平移
settings    系统设置、背景图及撤回上限
timeline    FPS、循环状态和所属动画列表
selection   当前场景对象类型与 ID
scene       粒子、碰撞体、路径和 Spine 数组
savedAt     保存时间

4.3 粒子与图片资源

粒子系统保存全部可编辑参数,包括:

  • 发射模式、持续时间和延迟;
  • 发射器形状和根变换;
  • 生命周期、速度、缩放、旋转与曲线;
  • 颜色、透明度、混合模式;
  • 修改器;
  • 碰撞、路径和骨骼跟随;
  • 图片资源与拖尾资源;
  • 对象显隐和所属动画。

PixiJS 纹理实例和粒子逐帧缓存不会写入 JSON。图片资源通过自身的预览 URL 或 Data URL 保存,配置加载时重新创建纹理。

4.4 Spine 原始资源内嵌

Spine 对象除属性、动画选择和骨骼元数据外,还保存原始资源副本:

sourceBundle.skeleton
sourceBundle.atlas
sourceBundle.textures[]

每个资源同时保存原文件名和 Data URL。恢复时重新创建同名 File

  • JSON 使用原 JSON 文件名;
  • SKEL 使用原二进制文件名;
  • Atlas 保留原 Atlas 文件名和内容;
  • 纹理保留 Atlas 中引用的准确文件名。

保持文件名一致是 Atlas 再次匹配多张纹理的关键。Data URL 只是文件内容载体,不会替代资源之间的文件名引用关系。

Spine 面板在首次加载成功后异步生成 sourceBundle,避免内嵌资源转换干扰当前画布中的实时 Spine 解析结果。


五、编辑器配置加载

5.1 校验

加载本地文件时只接受 .json,并依次检查:

  1. 是否为有效 JSON
  2. format 是否为 SpineParticle.EditorConfig
  3. 配置版本是否为 1
  4. 场景是否包含粒子、碰撞体、路径和 Spine 数组。

失败时保持当前编辑器状态,并显示具体错误。

5.2 原子恢复流程

配置加载先在临时数据中完成资源准备:

  1. 深度复制配置数据;
  2. 补齐旧粒子参数默认值;
  3. 重建粒子和拖尾纹理;
  4. 还原 Spine 原始文件;
  5. 解析骨架、Atlas 和多纹理;
  6. 全部解析成功后再替换当前场景;
  7. 注册新的 Spine 运行时资源;
  8. 修复对象选择和所属动画;
  9. 重新计算时间轴长度。

如果内嵌 Spine 资源解析失败,已临时创建的纹理会释放,不会把半完成场景覆盖到编辑器中。

5.3 Spine 运行时刷新

重复加载配置时,Spine 对象 ID 可能相同。加载流程会提升 assetVersion,确保运行时层识别为新资源并重新创建 Spine 显示对象,而不是继续使用旧实例。

资源加载完成后会恢复:

  • Spine 画布渲染;
  • 动画列表和动画时长;
  • 当前选择的 Spine 动画;
  • 骨骼层级树;
  • 当前选中骨骼;
  • 粒子系统保存的 Spine ID 与骨骼名称绑定。

5.4 加载后自动播放

配置和预设加载完成后统一执行:

frame = 0
recorded = false
playing = true

因此首次加载和连续加载同一份配置都会从头自动播放,不再依赖场景深度监听是否检测到数据变化。


六、预设体系

6.1 预设目录

预设文件放置于:

public/Preset/

每个预设都是与“保存配置”完全相同的 SpineParticle.EditorConfig JSON,因此预设和本地工程配置共用一套解析、校验和资源恢复流程。

6.2 自动索引

Vite 插件会扫描预设目录中的全部 .json 文件并自动生成:

public/Preset/index.json

索引生成时:

  • 排除 index.json 自身;
  • 按中文文件名排序;
  • 使用文件名去掉 .json 作为界面名称;
  • 开发服务器监听文件新增和删除并刷新列表;
  • 生产构建开始前重新生成索引。

目录中没有配置文件时,下拉框显示“无预设文件”并置灰。

6.3 当前预设

当前项目包含:

  • 纯粒子.json
  • 纯粒子-路径.json
  • 纯粒子-碰撞.json
  • 纯粒子-spine.json
  • 空场景.json
  • 默认粒子.json

带 Spine 的预设内嵌 bingo.jsonbingo.atlasbingo.pngbingo_2.png,加载后可直接显示 Spine、动画列表和骨骼树。

6.4 文件命名规则

阶段测试发现,文件名包含 + 时,经 URL 编码后开发服务器会返回应用 HTML,而不是目标 JSON,最终表现为“配置文件不是有效的 JSON”。

为确保开发环境和静态托管环境行为一致,组合预设统一使用连字符:

推荐:纯粒子-路径.json
避免:纯粒子+路径.json

预设加载失败时,界面在原始错误后追加:

请检查预设文件命名

七、代码结构

本阶段新增或重点调整:

文件 职责
src/editor/editorClone.ts 安全深度复制编辑器可序列化数据
src/editor/editorHistory.ts 撤回快照、合并、上限和 Spine 资源引用
src/editor/useEditorShortcuts.ts 全局快捷键、画布焦点和输入保护
src/editor/editorConfig.ts 配置创建、下载、校验、加载和资源恢复
src/spine/spineSourceBundle.ts Spine 原始文件 Data URL 内嵌与还原
src/spine/spineAssetRegistry.ts Spine 配置恢复和撤回所需的资源生命周期
src/views/ParticlePanel.vue 保存、加载、预设列表和结果提示
src/views/Stage.vue 快捷键接入、撤回按钮和加载后的运行时刷新
vite.config.ts 预设索引自动生成和 Spine 依赖去重

配置、历史与快捷键逻辑已从主画布和主属性面板中拆分,避免继续扩大单文件职责。


八、验证结果

已完成以下实际验证:

  • Ctrl/Cmd + S 可以下载编辑器配置;
  • 配置文件名按时间生成且 JSON 格式有效;
  • 修改粒子名称后保存,再次修改并加载,名称恢复为保存值;
  • 系统设置、背景图数据、画布视图和场景对象写入配置;
  • 含 Spine 的配置保存后文件约 11MB,资源数据完整内嵌;
  • 含 Spine 配置重新加载后,Spine 名称恢复;
  • Spine 画布图像正常显示;
  • 14 个 Spine 动画及“无”选项正常恢复;
  • 骨骼层级树正常恢复;
  • 页面未出现资源解析或渲染错误;
  • 纯粒子.json 加载成功;
  • 纯粒子-路径.json 加载成功,场景包含粒子与路径;
  • 纯粒子-碰撞.json 加载成功,场景包含粒子与碰撞体;
  • 纯粒子-spine.json 加载成功,场景包含粒子与 Spine;
  • 空场景.json 可以加载为零对象场景;
  • 默认粒子.json 加载成功;
  • 同一 Spine 预设连续加载两次,两次都从第 0 帧自动播放;
  • 第二次加载后帧数从 40 推进到 59,播放按钮保持“暂停”状态;
  • 浏览器控制台无错误和警告;
  • npm run build 生产构建通过。

构建仍存在 Vite 主产物超过 500kB 的提示,不影响功能和构建结果。


九、当前限制

  1. 当前只支持单向撤回,尚未实现重做;
  2. 撤回历史只存在于当前页面内存中,刷新页面后清空;
  3. 撤回不保存当前播放帧、播放状态、画布选择和粒子录制缓存;
  4. 配置格式当前为版本 1,尚未建立跨版本迁移器;
  5. Spine 和本地图片使用 Data URL 内嵌,资源较大时配置文件体积明显增加;
  6. 保存配置始终下载新文件,尚未提供覆盖保存、最近文件和自动保存;
  7. 浏览器安全限制下无法记住原本地文件路径;
  8. 预设依赖构建时生成的索引,纯静态部署后新增文件需要重新构建;
  9. 预设命名目前通过规避 + 保证兼容,尚未建立完整的文件名字符校验;
  10. 配置导入目前只接受 JSON,尚未支持 YAML;
  11. 配置文件没有压缩,包含 Spine 多纹理时下载和解析成本较高;
  12. 主包仍包含 Spine 运行时和主要编辑器模块,尚未动态拆包。

十、阶段十建议

  1. 增加重做功能和 Ctrl/Cmd + Shift + Z 快捷键;
  2. 增加配置格式迁移器,支持未来版本平滑升级;
  3. 为预设文件名建立创建、校验和错误定位工具;
  4. 提供自动保存、最近配置和页面异常恢复;
  5. 支持压缩工程包,把 JSON 与 Spine、粒子图片资源拆分存储;
  6. 增加配置导入前预览、差异对比和合并模式;
  7. 为配置与预设建立自动化往返测试;
  8. 对无效 ID、丢失骨骼、缺失纹理和旧字段提供迁移报告;
  9. 增加工程名称、作者、备注和自定义元数据;
  10. 开始设计正式导出结构,把所属动画、粒子系统和 Spine 骨骼绑定映射到导出数据;
  11. 对 Spine 和编辑器主模块进行动态加载,降低初始包体积;
  12. 增加配置资源大小统计和大文件保存提示。