feat: TS 构建管线、Spine 抓取器与 wallpapers/ 唯一真相来源

把项目从「手写 dist/」改成「wallpapers/ 是唯一真相来源,dist/ 由 pnpm build 生成」,
并补上配套的类型、门禁与抓取器。一次提交落地整条管线,因为拆开会留下不能构建的中间态。

- src/:运行时与模拟器源码(TS,strict),编译到 build/ 再拷进各分发
- tools/:build / dev / check-{syntax,paths,dist},以及抓取器与回归门禁 tools/checks/
  (.scratch/ 下那批一次性脚本移入 tools/checks/ 并入库为长期门禁)
- wallpapers/:七档壁纸的源数据 + README.md(id/音频/预设的完整规范)
- docs/adr/0005-0008:构建管线与分发拓扑、模拟器契约、自包含 sim、每骨架资源布局
- .gitignore:排除 .scratch/ 的参考资料副本(上游 spine 整仓克隆 ~1.2 GB、
  抓取侦查数据 ~680 MB)与调试转储;这些是本地调查材料,补偿会让仓库无法克隆
- 归一化 .gitignore/CONTEXT.md 行尾(工作区 CRLF、索引 LF 造成的整文件假 diff)

同时修掉三档卡住构建的未完工壁纸:
- kv45 的 meta.json 里 id 还是抓取期场景名 scene_main,经 downloader promote 正名为 kv45
- shajin / zhigengniao_juheye 的 meta.json 误用了骨架描述文件(name/spine/animations/pages)、
  且都缺 preset.template.json;现按规范重建:骨架沉到 spines/<名>/(spine-ts 按 atlas 所在
  目录解析贴图页)、补上元数据与单骨架预设,并清掉 zhigengniao 骨架里指向作者机的绝对路径
- 顺带 promote 已在 sources.yml 里的 kv46(月升之前,与兽共舞)

pnpm check 五道门全绿:10 个分发 / 7 档壁纸 / 141 处引用自包含。
This commit is contained in:
Shuery committed 2026-10-02 01:27:02 +08:00
1 parent b8eee05d78
commit 3f11426964
297 files changed
+216627 -1926

No files matched your search

@@ -0,0 +1,83 @@
# 14 — 面板动效
Status: resolved
Type: task
## 需求
> 给这个壁纸设置添加一些细腻的动画吧
## 一条原则
**只做解释状态变化的动画**——东西从哪来、去哪了、刚才是哪个变了。
面板是常驻 UI。装饰性的循环动画(呼吸、闪烁、渐变流动)只会让人分心,而且这个面板
每改一个属性就会重画一次,任何"一直在跑"的东西都会变成噪音。所以整套动效里
**没有一条 `@keyframes` 是持续运行的**。
## 加了什么
| 位置 | 动效 | 它在解释什么 |
| --- | --- | --- |
| 抽屉 | 曲线改成 `cubic-bezier(.22,.61,.36,1)` | 纯 `ease` 结尾会急停 |
| 面板刚滑出 | 逐行错开上移淡入(`--i` × 16ms) | 这些东西是"刚出来"的 |
| 条件新出现的行 | 同样的入场,不错开 | 它是被勾出来的 |
| 行悬停 | 底色高亮 + 图标放大 1.16 | 指针现在在哪一行 |
| 复选框 | 自绘,勾靠 `background-size` 从 0 长出来 | 刚才是哪个开关变了 |
| 下拉箭头 | 展开时翻 180° | 列表开着 |
| 下拉/取色器弹层 | 缩放 + 上移出现 | 它从按钮那儿长出来 |
| 色块 | 悬停放大;确认后弹一下 | 颜色变了但位置没变,不弹容易看不出 |
| 重置 | 悬停时图标转半圈 | 这是"复位" |
| 确认/取消 | 悬停提亮、按下下沉 1px | 按到了 |
| 右边缘把手 | 悬停淡入并左移 2px | 这里能滑出东西 |
## 两个容易做错的地方
### 入场不能每次重画都重播
`paintProps()` 是 `host.textContent = ""` 然后整块重建。如果入场动画挂在
`#wesim[data-open="1"] .row` 这种选择器上,那么**每改一个属性**——拖一下音量、勾一个开关——
整个面板都会重播一遍动画,看起来像闪屏。
所以:
- **刚滑出**那一下:给根节点打 `data-enter="1"`,520ms 后摘掉。带令牌,连着开关几次
只有最后一次的定时器能摘。
- **条件新出现的行**:`paintProps` 记着上一次可见的属性键,只有新冒出来的才加 `.row-enter`。
那 4 个颜色滑杆是个例外:它们不是属性表里的键(是 WE 内置的),走不到按 key 认新的那套,
所以单独用 `colorOptionsShown` 判一次"上一次它们不在"。
### 复选框不能用 `::after` 画勾
`<input>` 是替换元素,**伪元素在它上面不生效**。所以勾是一张内联 SVG 背景图,
靠 `background-size: 0 0 → 11px 11px` 长出来(`background-size` 是可过渡属性)。
## prefers-reduced-motion
整套动效在 `@media (prefers-reduced-motion: reduce)` 里被关掉。这不是可选项:
前庭功能敏感的人会因为界面动而难受,而这套动效对可用性没有任何贡献。
## 验证
`tools/checks/verify-panel.mts` 第 ⑩ 组,全部通过:
- 滑出后 `data-enter="1"`、行上跑的是 `wesim-row-in`、`--i` 是 0,1,2,3,4
- 播完 `data-enter` 被摘掉(不会每次重画都重播)
- 勾「显示颜色选项」后,**只有**亮度/对比度/饱和度/色调偏移四行带 `.row-enter`
- 复选框 `appearance: none`(确认是自绘的)
- 展开下拉 → `aria-expanded="true"` 且箭头 `matrix(-1,0,0,-1,0,0)`(翻过来了);Esc 后复位
- `Emulation.setEmulatedMedia` 模拟 reduce → 动画与过渡时长都降到 ~0
## 测出来的三个真问题
1. 颜色滑杆走不到 `isNew(key)` 那套,永远不带入场标记(上面已说)。
2. **点开下拉时先把 `aria-expanded` 设成 true,紧接着 `openComboFor` 内部的 `closeCombo`
又把它清掉** —— 顺序反了,箭头永远不翻。改成 `openComboFor` 之后再设。
3. 测试自身:动效那一段先移到远处再移到边缘。前面点过「取消」会把 `armed` 置 false,
而它只有"指针离开边缘"才复位——不先走开一次,合成指针根本打不开面板。
## 回归
全绿:`pnpm check`、调试服与浏览器冒烟、热更新、四档自包含包 `file://`、静态托管预览、
发布产物里动效代码 0 处(`wesim-row-in` 计数为 0)、6 组渲染与重构前逐像素相同。