Files
tamabox/.workbuddy/memory/2026-10-20.md
T

118 lines
9.6 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.
# 2026-10-20
## 01:10 shiroko 主题补「空气层」
- 用户问「还有没有其他元素,贴合主题又不突兀」。结论:场景压白 38% 后整页亮度只有 235~246,
再摆物件(书包/粉笔/纸飞机)一定会像贴纸,所以走**纯渐变造光**路线。
- 做了 4 个候选截图(A 纯窗光 / B 白散景 / C 光环符号 / D 组合),用户选 D。
⚠️ **B 是反面教材**:白色散景叠在已经压白的场景上,实测差异 0.14 级,肉眼完全不可见。
要"提亮"必须先有暗部,真正起作用的是「底部压深 + 暖色光斑」的组合。
- 最终 `--tb-deco` 后 4 槽:左窗光柱(112deg)、右侧 120px 暖散景(88% 30%)、
脚下 560×170 地面光斑(28% 94%)、底部 24% 压深。亮度差 3~9 级。
- 验证手段(本轮**模型读不了图**,全靠数值):留白区差分(与候选 D 差 0.0)、
分区亮度表、横向扫描相邻像素差 max 4(判色阶断层)、PNG 体积比对。
- ⚠️ 造预览页两个坑:① 覆盖块必须包在 `<style>` 里,裸写会被当正文渲染,整页布局炸掉;
② `--tb-deco` 各层之间**漏逗号**会让整条声明失效 → 人物和所有背景层全没,且各变体看起来"完全一样"。
以后先 diff 两个变体的 CSS 文本再截图。
- `StaticVersion` → `20261020a`;提交 `fb94b8c` 已推送。文档 `docs/theme-shiroko.md` 加「空气层」一节。
## 08:30 重画光环
- 用户反馈「光环变形太奇怪,而且中间没有扣干净」。根因两条:
① AI 画的环本身歪(bbox 291,93–584,232,比头还宽、偏移到左边);
② 环内是**封闭白孔**(面积 5190px 的包围区域),四角 floodfill 进不去 → 抠完环里糊着一团白。
- 做法:非白像素从环上一点漫水拿到独立连通域(与头发不连通,头部顶端在 y≈265,环只到 232),
整块抹白;**先把 alpha 建好,再在 RGBA 上画新环**——环心天然就是透明的,不用给封闭孔补洞。
- 新环参数:中心 (515,160)、100×34、线宽 10、-7° 倾斜、4 倍超采样后 LANCZOS 缩小、
外加 45% 模糊柔光;颜色 (127,211,220),压白 16% 后实测环心 (164,220,224)。
- 坑:擦除矩形右边界要绕开**灰色狼耳**(x>630,y 190-260,颜色 (139,140,146) 不是青色),
差点一起抹掉。判据是连通域 bbox 而不是"上方全是空白"。
- 验证:alpha 字符图确认环闭合、环心 alpha=0;渲染后页面里青色像素 bbox (201,467)-(271,649),
环在 y 468-486,头顶约 505,间距正常。
- `StaticVersion` → `20261020b`,图片 `?v=20261020b`;提交 `2e9bd6b` 已推送。
## 09:40 部署反馈三修 + 自行车/步枪
- **狼耳顶端被削平**:上一版用矩形 `(281,83)-(594,242)` 抹旧光环,右下角正好切到左耳尖
(耳尖在 y≈185、x 420-480)。改成只抹光环的**非白连通域**(bbox 291,93-584,232,与头发不连通)。
- **手内侧 / 大腿内侧白没抠干净**:那是**闭合**的白色区域,四角 floodfill 进不去。
加封闭白孔检测(>=246 且不与边缘连通、面积>=40)整块掏成透明。
⚠️ 阈值必须 >=251 才能当"背景":背景恒为 (253,253,253),而**白袜子是 237**,
用 246 当背景阈值会把袜子一起吃掉(第一版就吃穿了一只袜子)。
- **人物像站在课桌上**:原场景前景全是课桌,根本没有地面。重出场景:
前景留空地、课桌退到右后方,人物脚下才是地板。
- **自行车 + 步枪**:独立素材 `props/bike.webp`(镜像成车头朝右、与人同向、压白 26%、
自带接触阴影),放在**人物身后偏左**。deco 层顺序 = 画在上面的在前,所以第一层是人、
第三层是车,车天然被她挡住。
- ⚠️ **`background-position` 的百分比是相对 `(定位区宽 - 图片宽)`**,不是相对视口宽。
人(117px)和车(397px)用同一个 `calc(50% - 901px)` 会差出 280px,车直接跑出屏幕只剩一片轮圈。
按各自宽度反解后:人 `calc(50% - 524px)`、车 `calc(50% - 612px)`。
- ⚠️ 道具**不能烘焙进背景**:背景走 `cover`,视口一变裁切量就变,和固定 px 的人物必然分家。
- 场景重出后色调用「逐通道均值/方差对齐旧场景」保持同一雾度;移动端从同图竖裁,避免两个房间。
- `StaticVersion` → `20261020d`;提交 `15aebd6` 已推送。
## 09:55 素材规格书
- 用户打算换工具自己生成素材 → 写了 `docs/theme-shiroko-assets-spec.md`:
画布/导出/显示尺寸、比例(人 1:3.41、道具 1.53:1、背景 16:9)、雾度(人 16%、车 26%、场景 30~38%+模糊 1.2~1.4px)、
构图硬约束(左侧 22% 前景必须是空地,否则又回到"站在课桌上")、换图清单与定位公式。
- 配色给的是**压白后的显示值** + 反算公式 `原色=(显示值-40.8)/0.84`,并特别标注袜子要用 `#ededed`
而不是纯白(纯白会和背景粘连,抠图必然吃穿)。
## 10:40 主题生成器(dev/theme-builder)
- 单文件 `dev/theme-builder/index.html`:上传背景/人物/道具 → 拖拽调位置 → 导出 zip,
解压到项目根即可新增主题。不联网、不起服务、图片全在浏览器本地转 WebP。
- 预览用**和线上同一套机制**渲染(pattern + deco 6 层 + page-image,size/position 对齐),
不是另画示意图;拖出来的「左沿像素」反解成 `calc(50% - Npx)`,换视口不跑位。
- 导出包:`static/css/themes/<slug>.css` + `static/images/themes/<slug>/*.webp` + `INSTALL-<slug>.txt`。
CSS 同时写浅色/深色两块,10 个必需令牌齐全——**实测通过 `TestThemeCSSComplete`**。
- zip 自己实现(STORE + CRC32,约 40 行),不引 CDN;`unzip -t` 无错。
- 踩坑:① 面板里 `c.text2` 写成 undefined(light 对象里才算出来的派生色,要用 `light.text2`);
② `contain` 模式如果不按内容裁画布,会留大片透明边 → 导出宽高比全错;
③ 预览容器 `grid-template-columns:340px 1fr` 会被 1512px 的 frame 撑破 → `minmax(0,1fr)`;
④ 无头 Chrome 下 `canvas.toBlob` 的回调在 `--dump-dom` 前不触发 → 全部改 `toDataURL` 同步化,
自检才能跑(`?selftest=1` 输出 CSS/zip 字节,`?demo=1` 载入示例素材)。
- ⚠️ 预览里深色必须走「暗色渐变 + deco none」,否则会拿白天场景图压深底(和导出结果不一致)。
## 11:05 主题生成器重做:真实页面画布 + 按页面作用域
用户原话:旧生成器「只针对当前遇到的问题,需要更通用」「示例页面和我的项目完全不一样」
「想针对箱主页面、问题页面、问题列表、设置页面分别配置」。
**机制层(新)**
- `internal/context.pageScope()` 按路径归类,`<html data-page-scope>`:
`box`(/_/{domain}) / `question`(/_/{domain}/{id}) / `admin`(/user/questions,/user/votes*)
/ `profile`(/user/*) / `vote`(/vote/{token})。首页与 `/explore` 返回了值但**不加载主题 css**,
所以生成器里不列它们(列了就是骗人)。
- ⚠️ 深色覆盖必须是**三重选择器** `html[data-theme="dark"][data-theme-style][data-page-scope]`:
浅色作用域块特异性 0,2,1 与深色块相同、且写在后面,二重选择器会被它盖掉。
- 装饰槽位 **6 → 10**(base.css 背景 8 → 12 层 = pattern1 + deco10 + image1)。
`TestDecoSlotCount` 逐文件逐声明检查,变异验证有效(写 6 个会 FAIL)。
**生成器(重写)**
- 画板 = iframe 加载 `outputs/preview-*.html`(真模板渲染)。**必须起本地服务**:
file:// 下父页面读不到 iframe 的 DOM(即使同目录),预览只能退回示意图。
`dev/theme-builder/serve.py` 把项目根当静态目录(只读)。
- 每个作用域独立「整页背景 + 最多 10 层装饰」,默认跟随全局;不产覆盖块就自动回退。
- 图层 = 图片 / 径向光斑 / 线性光;9 宫格锚点 + 像素偏移;图片层可在画板上直接拖。
- ⚠️ 位置统一 `calc(0%|50%|100% ± Npx)` 两值:百分比是相对 (容器 − 图片)。
**不要** `left/bottom` 关键字混搭 —— 「水平居中 + 垂直贴底」是三值语法,非法时整条声明作废
→ 图层静默掉到左上角(这是之前踩过的坑,这次直接规避)。
- ⚠️ 配色只让填 6 个基础色,另 4 个必需令牌派生:`surface-2` 往 **text** 混(浅色下变深、
深色下变亮,方向自动对),`text-secondary/muted` 往 bg 混,`primary-weak` 加 alpha。
漏了 `--tb-primary-weak` 时 `TestThemeCSSComplete` 只报「缺少」,页面看着没问题,很容易混过去。
- 自检钩子:`?dump=css` / `?dump=zip`(写进 `<pre id="dump">`),配合 `--dump-dom` 回归。
**验证**(都是实测,不是推断)
- 生成器导出的 CSS 放进 `static/css/themes/` → `TestThemeCSSComplete` + `TestDecoSlotCount` 双绿;
删掉深色块做变异 → FAIL,说明测试真的在查。
- 真实箱主页计算样式:image/size/position/repeat/attachment **各 12 层**,前几层尺寸与 shiroko 一致
(auto 400 / 96x13 / auto 259 / 100%×3),确认扩槽没打乱顺序。
- 临时主题 `zztest` 验证:box 页有人物、question 页 `--tb-deco: none×10` 后人物消失;
不写覆盖块时回退全局(人物仍在)。
**顺手发现**:`.gitignore` 写的是 `./outputs`(无效写法),导致 247 个 outputs 文件被跟踪,
每次跑 `TestGenPreview` 都会产生一堆 M。没擅自改(会让人以为要清理历史产物),留待用户决定。