Files
SpineWallpaper/.scratch/build-pipeline/issues/14-panel-animations.md
T
Shuery 3f11426964 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 处引用自包含。
2026-10-02 01:27:02 +08:00

84 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 组渲染与重构前逐像素相同。