切换外观
变形 · 动起来之前:参考、数据、故事
状态:2026-10-28。第四轮候选 04 变形按六步流程(reference → data → story → motion → direct → ship)做成完整形式 sketches/morph.html。第 1–4 节在动代码之前写下,故事与交互先定;实现、与故事的出入、自审与验证见第 5–6 节。原型探索,不是规范。范本是让位图(复盘工具的两层法则、讲一遍的规矩)与 C 流动形态(所有份额同一条缓动、同起同落,和恒定),交互取共用模块 motion/ix.mjs,两层法则见 CONCEPTS.md。数字都由 scenario.mjs 回放现算,推算脚本只留在本机,不入库。
1 参考:草图怎么讲,哪里讲不动
草图的讲法。 探索代理的静态草图(本机 scratchpad,不入库)读 composite f26(8/16 00:00),左右两块圆阵:左边“收到的”,面积 = 两周里关联到这件事的输入条数占比;右边“给出的”,面积 = 此刻份额占比;两块用同一套位置,每件事一个虚线圈,圈的大小取两边较大的那个;黑是家里,白是工作。右下两个大字“149 → 6”“29 → 24”。
哪里讲不动。
- 两拍并排,不是变形。 论点是“同一件事从收到多少变成占多少”,但读者要在两块之间来回找同一件:左边 master CI 在中下,右边要靠虚线圈的位置去对。Douïeb 的原作把论点放在一段连续变形里,草图只能把起点和终点摆在一起。
- 计数口径与别的形式不一。 草图按
relatedIds里出现的每个 id 各记一次(一条输入点了两件事就算两次),只认此刻的 id,不认批次声明里的引用,也不沿合并上溯。整理脉冲、份额拨盘与 C 的“本轮进了它 N 条”用的是另一条规则(第 2 节),同一件事在两张图上条数对不上:master CI 草图是 149,按脉冲的规则是 141;待审 PR 草图 39,沿合并接上旧的两版之后是 52。 - 只有一帧。 不能逐帧,看不到这段变形在两周里每一轮是什么样,也没有悬停与展开。
- 小圆的字压在别的圆上。 1 份的圆半径约 20 px,标签排在圆下方,与邻圆的虚线圈相撞(“开学文件 1 份”“Kerberos 1 份”);“65KB 上传”溢出了自己的圆。
- 留白不在图上。 64 份里此刻用了 63,剩下的 1 份没有画;两块的总面积相同是草图写死的比例,看不出“同一个池”。
从参考搬什么,不搬什么。
| 要素 | 出处 | 搬过来 | 不搬 |
|---|---|---|---|
| 原地变形 | #96 Douïeb “Land doesn't vote, people do”:同一套图例,每个市镇缩成面积等于选民数的圆,留在原地附近 | 同一件事同一位置,面积从条数缩放到份额;黑白图例两态不变;整体印象在变形里翻转(收到的白多,给出的黑多) | 地理位置(这里的位置只是稳定的排布,左工作、右家里);Dorling 式的碰撞漂移:原作的圆在变形中互相推开,这里每件事的位置在两态里完全不动 |
| 最小间距 | #92 Hobbs:线与线保持最小间距,“太近就停” | 每件事占一个够放下两态中较大那个的位子,位子之间留固定间距,所以变形时谁也碰不到谁 | 流场与短划 |
| 总量守恒 | #75 Liquid Glass:屏幕总高固定,数字给新来的让形体 | 两态的墨量相等,变形中任何时刻都相等(见下一行) | 玻璃折射与高光;数字字形随面积变矮(数字只在落定那一帧换) |
| 同起同落 | C 的长缩拍:所有份额同一条缓入缓出、同一对 t0 / t1,任何时刻份额加留白都是 64 | 变形与换轮都照做:所有圆同一条缓动、同起同落,不过冲;面积线性插值,所以圆面积之和 + 留白在每一帧都是 64 份的面积 | 拨盘扇区 3.7% 的过冲:面积过冲就是多出来的份额 |
| 讲一遍 | 让位图、回应时序、C:只在顶层直接打开时讲一遍,任意键跳过,停在故事最后一帧 | 照搬触发条件、跳过与重演;讲完的标记留到第一次交互 | 循环 |
| 概念层 | 让位图:约一成,只在过账那一秒动,静止为零 | 只有变形中的一圈灰色余影(圆的边缘 0.2 秒前在哪里),平涂、不进文字,落定后为零 | 粒子、飞点、尘埃、辉光、余辉;用户刚嫌树图与 C 换轮时飞的点多 |
| 朱红 | 拨盘、脉冲:只给回应路径 | 只给“此刻有开着的问题”:名字前一个 5 px 朱红小方块 | 朱红不表示量,不表示家里或工作 |
2 数据:输入怎样关联到此刻的事项
口径(与整理脉冲同一规则)。 页面用 variants/shared.mjs 的 records(scenario.mjs 经 engine.mjs 重放)现算,不读 data.json、不加字段。
- 一条输入指向哪件事:先看它到达那一轮的批次声明里有没有引用它(
batch.declarations[].sources[].ref === 'event:<id>',取那条声明的id),没有就取relatedIds[0](整理脉冲rounds[].events[].target、C 的粒子落点同一规则)。噪音在 composite 里一条也不指向事项,所以自然不进;暂缓与重复照算,它们是收到了、也指向了这件事,只是没被采用。 - 关联到此刻的哪件事:从那个 id 沿合并(
status: 'merged'的merged_into)与父级(parent_id)上溯到正在看的这一帧的根层事项(脉冲的rootAt(i, id),i取此刻而不是输入到达的那一轮)。所以后来并进来的旧条目,它们收到过的输入也算在新条目上;此刻已撤下、没有并入任何一件的,它的输入不算在任何一件上。 - 同一件事换过 id:只认回放里记了的
merged_into。composite 里所有“同一件事换了个 id”都走的是合并:合并日志一路并成“合并 8/3–10”(f16 时 318 条),旧的待审 PR 两版在 f18、f22 并进pr-reviews-0814,旧的开学文件与头虱在 f22 并进signe-school-start;撤下后再恢复的(小龙虾派对 f22 撤下、f28 恢复)id 不变,原来的输入照样算。撤下一件、同一轮另起一个新 id 而没有记合并的,回放里没有“它们是同一件”的记录,旧 id 的输入不接过去。 - 收到 = 从 f01 到此刻,按上面两条落到这件事上的输入条数(累计);给出 = 此刻
records[i].state.root.items[].share。 - 两态的面积:给出态一件事的面积 = 份额 × K(K 是每份的面积,整页一个常数,同样的份额在任何一轮都一样大);收到态 = 这件事的条数占此刻各件条数之和的比例 × 此刻已分配的份额 × K。两态的墨量都是“已分配份额 × K”,留白(64 − 已分配)画成虚线圈,两态一样大,所以画面上的总面积始终是 64 份。卡上的“折合”就是收到态的这个数(条数占比 × 已分配份额)。
- 家里还是工作:一件事两周里落到它身上的输入按流(
event.stream)计,work过半就是工作(白),否则是家里(黑;家庭、生活问答、社区与订阅都算家里,与拔河草图“生活问答并入家里”一致)。手写情境没有stream,按motion/dial-model.mjs的车道规则把 channel 归到工作、家庭、生活、订阅,“用户消息”等不计;这是渲染层的近似。用两周全程而不是到此刻,是为了让一件事的黑白不在两周中途翻面。
全量(composite)。 29 帧、3196 条输入;1322 条指向某件事(批次声明引用 641 条,relatedIds[0] 681 条),其中采用 1177、暂缓 118、重复 27;不指向任何事的 1874 条(噪音 864、暂缓 999、重复 6、未判 5)。声明引用与 relatedIds[0] 指向不同事项的只有 3 条;relatedIds 不止一个的 31 条,草图把它们各算了不止一次。
故事这一帧:composite f26(8/16 00:00「车道下的铜管裂了」,frames[26])。f01–f26 共 3051 条输入,关联到此刻 14 件的 464 条;已分配 63 份,留白 1。按收到排:
| 事项 | 家里 / 工作 | 收到(采用 · 暂缓 · 重复) | 给出 | 收到占比 → 份额占比 | 折合 |
|---|---|---|---|---|---|
| master CI | 工作 | 141(133 · 2 · 6) | 6 | 30% → 9% | 19.1 |
| 猫看病 | 家里 | 60(58 · 1 · 1) | 6 | 13% → 9% | 8.1 |
| 待审 PR | 工作 | 52(51 · 0 · 1),其中 14 条沿合并接上 | 6 | 11% → 9% | 7.1 |
| 母亲换水管 | 家里 | 45(44 · 1 · 0) | 3 | 10% → 5% | 6.1 |
| 主水管 | 家里 | 29(28 · 1 · 0) | 24 | 6% → 38% | 3.9 |
| Kerberos | 工作 | 26(23 · 3 · 0) | 1 | 6% → 2% | 3.5 |
| Ture 发烧 | 家里 | 22(20 · 2 · 0) | 1 | 5% → 2% | 3.0 |
| 后刹 | 家里 | 21(12 · 7 · 2) | 3 | 5% → 5% | 2.9 |
| FTPS 计时 | 工作 | 19(19 · 0 · 0) | 6 | 4% → 9% | 2.6 |
| 65KB 上传 | 工作 | 16 | 3 | 3% → 5% | 2.2 |
| 开学文件 | 家里 | 15(6 · 3 · 6),其中 13 条沿合并接上 | 1 | 3% → 2% | 2.0 |
| 漫画 | 家里 | 12 | 1 | 3% → 2% | 1.6 |
| 风扇 | 家里 | 4 | 1 | 1% → 2% | 0.5 |
| rc1 | 工作 | 2 | 1 | 0.4% → 2% | 0.3 |
收到占比的分母是此刻 14 件的 464 条,份额占比的分母是 64 份。家里:条数 208 / 464 = 45%,份额 40 / 63 = 63%(工作 23 份,留白 1)。收到最多的是 master CI(141 条 → 6 份),份额最多的是主水管(29 条 → 24 份):master CI 收到的是主水管的 4.9 倍,份额只有它的四分之一。
两周里(composite)。 每一轮都算一遍(f01–f28):28 轮里收到最多的那件,从来不是份额最多的那件,它拿到的份额最多 6 份(f23–f28 的 master CI)。前半段收到最多的是合并日志(f16–f17「合并 8/3–10」318 条 → 1 份)和问答回复(f20 153 条 → 1 份),份额最多的一直是母亲换水管(f01–f22);后半段是 master CI 对猫看病(f23–f24)、对主水管(f25–f28)。按条数看,家里在 f01–f17 只占两到三成多(23%–36%),份额却 17 轮里有 16 轮过半(只有 f02 是 47%);f18 问答回复(生活问答,算家里)进来以后,条数里家里到了 66–67%,份额里到了 86–92%。
手写情境(story)对照。 37 帧、112 条输入;102 条指向某件事(声明引用 75、relatedIds[0] 27),采用 84、重复 10、暂缓 6、噪音 2(手写情境里有 2 条噪音也点了事项,照算);声明引用与 relatedIds[0] 不同的 38 条,所以这里两条规则差得比 composite 多。故事帧取 f15(10/17 10:00「陪妈妈改约周日11点,双方已确认」,frames[17],与让位图手写情境的第一拍同一轮):6 件收到 46 条,已分配 46 份,留白 18。
| 事项 | 家里 / 工作 | 收到 | 给出 | 收到占比 → 份额占比 |
|---|---|---|---|---|
| 发布 | 工作 | 11 | 3 | 24% → 5% |
| 妈妈 | 家里 | 10 | 24 | 22% → 38% |
| 试用 | 工作 | 8 | 6 | 17% → 9% |
| 筛选 | 工作 | 8 | 6 | 17% → 9% |
| 费用 | 工作 | 5(2 条沿合并接上:账单、查重在 f04 并为费用) | 1 | 11% → 2% |
| 厨房 | 家里 | 4 | 6 | 9% → 9% |
家里:条数 14 / 46 = 30%,份额 30 / 46 = 65%。手写情境里“收到最多 ≠ 份额最多”不是每轮都成立:f07(筛选 7 条 → 24 份)、f18(妈妈 12 → 24)、f25–f27(发布 15 → 24)收到最多的也拿到最多,冷启动两帧只有一两件。所以论点不能写成“收到最多的从来拿不到最多”,只写这一轮。
回放里有、图上还没用的。 每条输入的来源(channel、作者)只放进详情卡与侧栏;子层的份额不画(composite 两周没有子层,手写情境的子层只在卡上列出)。回放里没有的:Agent 为什么给这件事这么多份(reason 是一句话,不是对条数的解释);“如果不按判断、按条数分”从来不是系统的一个状态,“折合”只是收到态面积的读数,卡上写明。
3 故事
一个论点。 收到多少不等于给多少:同一批事项留在原位,面积从“收到多少条输入”变成“占多少份”,这段变形就是 Agent 的判断。(composite:master CI 两周 141 条输入只占 6 份,车道下的主水管 29 条就占 24 份;收到的条数里家里不到一半,份额里家里将近三分之二。)
英雄数字:141 → 6。 收到最多的那件事,收到几条、给了几份。它放在侧栏“这一轮”的顶上,字高 48 px、等宽字,“141”与“6”之间一个箭头,下面小字“master CI · 收到最多”;紧接着一行小一号的对照“29 → 24 · 主水管 · 份额最多”。每一轮都有这样一对(第 2 节),换轮时在落定那一帧硬切;两件是同一件时只写一行。不放进图里,是因为图上每个圆都有自己的数,再放一个大数会压住圆;图上只在讲一遍的第 3 拍给这两件各挂一条注。
三拍(composite 停在 f26,story 停在 f15;共约 7 秒。帧号是页面常量,不写进数据)
| 拍 | 时长 | 发生什么 | 观众此刻 | 在动 / 只在节拍上落定 |
|---|---|---|---|---|
| 0 | 0–0.4 秒 | 图上只有留白的虚线圈(1 份)与左上角的说明“收到:两周里关联到它的输入”;侧栏写这一轮,英雄数字是“… → …” | 一张空图 | 什么也不动 |
| 1 收到 | 0.4–2.4 秒 | 14 个圆从无到有,同一条缓出、同起同落长到收到态(1.0 秒);名字随圆淡入,条数在 1.4 秒落定;同一刻英雄数字写出“141 →”“29 →”,侧栏的家里 / 工作条写出“收到 464 条:家里 45%”。之后静 1.0 秒 | 收到最多的是工作:master CI 一个白圆最大 | 动:圆长出、名字淡入。落定:条数、英雄数字左边、收到条 |
| 2 变形 | 2.4–4.4 秒 | 所有圆原地胀缩成给出态(1.4 秒,同一条缓入缓出,同起同落,不过冲):master CI 缩到原来的三成,主水管胀到原来的六倍多,成为最大的黑圆;每个圆离开时在收到态的大小留下一道细圈。3.8 秒落定那一帧:圆里的数从“141 条”换成“6 份”,左上角说明换成“给出:此刻的份额”,英雄数字补上“→ 6”“→ 24”,侧栏写出“给出 63 / 64 份:家里 40”。之后静 0.6 秒 | 同一批事、同一个位置,黑白翻了过来 | 动:圆的面积、一圈 0.2 秒的灰色余影(概念层)。落定:所有数字、说明、英雄数字右边、给出条 |
| 3 放大与压小 | 4.4–7.0 秒 | master CI 的细圈(收到)与主水管的黑圆(给出)同一帧描 1.6 px 墨边,旁边各淡入一条注(0.2 秒):“141 条 → 6 份 · 收到的 30% → 份额的 9%”“29 条 → 24 份 · 6% → 38%”;侧栏“放大 / 压小”两列各把这一件排在第一 | Agent 压小了谁、放大了谁 | 动:描边与注淡入。落定:其余不动 |
讲完后页面就是普通的复盘工具,停在 f26 的给出态(地址栏 frame=26),描边与两条注留到第一次悬停、按键或点按为止。
为什么从空图起。 第 1 拍可以直接从收到态静止开始,但那样第一眼就是两态中的一态,读者不知道面积是什么;从无到有长出来,面积“是收到的条数”这件事由动作本身说出来,第 2 拍才有对照。第 1 拍的长出不守恒(墨量从 0 涨到 63 份),这是有意的:它说的是收到,还没有分;第 2 拍起守恒。
两层。 信息层(九成以上):圆、细圈、留白虚线圈、名字与数、朱红小方块、左上角说明、第 3 拍的描边与注、侧栏。只用墨黑、纸白、灰与一个朱红;只在节拍上落定。概念层(不到一成,静止为零):变形与换轮中圆边缘的一圈灰色余影,宽度是圆的半径在最近 0.2 秒里走过的距离,透明度 0.16,只用灰,不带文字、数字与颜色;它和信息层共用同一个圆、同一个半径。圆不动的轮(份额与条数都没变)不画余影。
动起来之前的约束
- 绝不动:同一帧里一件事的位置(两态共用,变形只改面积);黑白只表示家里与工作;留白虚线圈在变形中不变。
- 同起同落:一次变形或换轮里所有圆、细圈与位置走同一条缓动、同一对起止,不过冲;面积按份额线性插值,所以任何一帧圆面积之和 + 留白 = 64 份的面积(第 1 拍的长出除外)。
- 数字只在落定那一帧换:圆里的数、说明、英雄数字、侧栏的条;名字的位置要变(圆里放不下了)的标签在动作开始时淡出、落定后淡入。
- 一件事一个位子:位子按两态中较大的那个圆加间距留出,变形时谁也碰不到谁;换轮时位置从上一轮的位子出发、只做最小的挪动,新来的从自己那一侧长出,撤下的原地缩没,并入的一边缩一边挪进它并入的那一件(只有这里画“谁到谁”,它是回放里记了的)。
- 不画配对:变形里不画“谁的份额给了谁”,只画每件事自己的两种量。
- 只读回放:条数、份额、家里 / 工作、问题开闭都现算;故事的帧号是页面常量;不改 scenario、shared、engine 与演示数据。
prefers-reduced-motion:讲一遍直接到终态,换轮与变形直接落定,不画余影。- 性能:圆、细圈与名字画在一张 SVG 里,余影在同一张 SVG 的底层;一次变形每帧只改属性,不重建节点。
手写情境的三拍。 照同一个时间表,停在 f15:第 1 拍 6 个圆长出,发布(工作)11 条最大;第 2 拍变形,妈妈(家里)10 条 → 24 份成为最大的黑圆,发布缩到 3 份;第 3 拍注“11 条 → 3 份 · 24% → 5%”“10 条 → 24 份 · 22% → 38%”。留白 18 份,比 composite 的大得多,虚线圈在两态都占一块。
4 交互
与份额拨盘、整理脉冲、让位图同一套标准,状态机、时序、卡与引线都走 motion/ix.mjs;本页只提供几何:一件事就是一个圆。
- 悬停
- 触发:鼠标移到圆上(圆与细圈中较大的那个,再放宽 10 px)、Tab 到它(每件一个隐藏按钮,按份额从大到小),触屏轻点一下;留白的虚线圈也算一件。
- 概要卡:名字、家里或工作、这一帧的条目标题;“收到 141 条 · 给出 6 份”;“收到的 30% → 份额的 9%”;本轮进了它几条(采用的,与脉冲的“本轮进了它”同数);它此刻开着的问题与期限。
- 其余怎么变:其余圆降到七成(
1 − 0.3 × X.dim),概念层余影降到四成;播放与讲一遍停在当前时刻,离开 0.15 秒宽限后卡 0.12 秒淡出,再 0.4 秒接着走。
- 展开
- 触发:点圆或它的概要卡,Tab 后 Enter 或空格。
- 动作:0 秒切点,顶栏旁白改成“这一件 · f26 · 8/16 周日 00:00 / 主水管”,侧栏切到“这一件”;0–0.3 秒圆(连同细圈与名字)沿它离画面中心的方向弹出 8 px(ease-out,过冲 3.7%);0.4–0.6 秒引线从圆的外缘沿同一方向出去再转向卡;0.6–0.9 秒详情卡从引线末端展开,先沿接上的那条边、再向外。卡贴在圆所在那一侧的图边,压到圆时放到它上方或下方。
- 详情卡(这一帧这一件):帧号与时间、家里或工作;标题;“收到 141 条 → 给出 6 份”与两个占比;收到的构成(采用、暂缓、重复,沿合并接上几条)与按来源分的前三组;份额逐轮小条图;这一件登记过的问题:此刻仍开着的写问法、期限与“去回答 →”(链到当前帧的 D:
../../index.html?variant=d&frame=<当前序号>,经withDataset带上?data=),已关的写怎么关上的(答掉写你的动作句,失效写“随改写失效”),不给链接;你对它的回应;摘要。不承载作答。 - 面板“这一件”(两周这一件):份额逐轮与收到逐轮两组小条图,此刻高亮、之后淡;到此刻的账(收到多少、给出多少、折合多少);问题关上的那几轮;摘要、依据、来源与版本(
itemDetailHTML,折叠)。点留白时是留白逐轮。 - 收回:Esc、点空白、再点同一件:卡 0.2 秒收起,引线 0.15 秒缩回,圆 0.2 秒落回,一帧切回这一轮的旁白与侧栏,0.4 秒后接着播。←/→、选帧、播放、切换收到 / 给出与合页顶栏选帧立即收起并照常执行。
prefers-reduced-motion时直接到终态。
- 收到 ⇄ 给出:工具栏两枚按钮(与让位图的“合并小额 | 逐件”同一种分段按钮),也可按 M;切换是一次 1.0 秒的变形(讲一遍里的第 2 拍是 1.4 秒)。直接打开与带
?frame=时停在给出态。 - 换轮:→ 一帧 0.7 秒;←、按住方向键、一次跳多帧、合页
followFrames同步时 0.42 秒;都从屏幕上当前的样子起算,所以打断不跳。空格连播每轮 0.7 秒换轮再停 0.9 秒,停在当前的态。 - 讲一遍:只在顶层直接打开、地址不带
?frame=、也不是从别的页面链过来(document.referrer是另一页)时演一次,任意键或点一下跳到终态;工具栏「▶ 讲一遍」可重演,讲的时候它变成「跳过 ▸▸」。带?frame=、画廊缩略图、合页 all.html 嵌入、体验站弹框与从别处链来的一律静止:不带帧时停在数据集的最后一帧(与批次记谱一样last: true,画廊卡片的“默认帧”才对得上),composite 是 f28,story 是 f34。 - 钩子:
window.foldMorph给出与foldYield同名同义的hover / unhover / open / close / ixAt / ix / paused / pointOf / ixState,另有nearOf / pick(给scripts/check-ix.mjs)、tell / skip / tellAt / play / stop / telling / playing / settled / phase / perf / resetPerf,以及本页的mode / setMode / rounds / plan / geom。window.foldSketch照旧是页框。
5 实现与出入
画法。 一张 SVG 三组:底层余影(概念层)、中层每件事一组(实心圆、细圈、键盘焦点圈、名字与数)、顶层第 3 拍的描边与注。每件事的状态是 {x, y, d, c}:d 是实心圆的份数、c 是细圈的份数(恒为收到态的折合),面积 = 份数 × K,半径取平方根;给出态 d = share,收到态 d = c,两者相差不到 0.8 px 时细圈不画,所以收到态里看不到细圈,给出态里细圈就是“它收到的大小”。整页只有一个过渡 tr,所有圆从屏幕上此刻的样子出发、同一条缓动、同一对起止;新的过渡从屏幕上的样子接着走,所以打断不跳。每帧只改属性(按值缓存,不变不写),不重建节点。
排布。 载入时一次算好全部帧(composite 29 帧约 100 ms,story 37 帧约 50 ms;改窗口大小时重算):每件事的位子按两态中较大的圆加 9 px 间距,圆外的名字也占一块矩形;第一帧从“工作在左、家里在右、留白居中”的锚点起螺旋找空位,之后每一帧从上一帧的位置出发(新来的从它并入前那件或它那一侧起),松弛 160 次,圆与圆、名字与圆、名字与名字都推开。K(每份的面积)先取图面积的四成除以所需,残余重叠超过 1.5 px 就缩一成二再算,最多 6 次;composite 是 2794 px²/份(1 份直径 60 px,24 份 292 px),一次就过,最大残余重叠 1.36 px;story 是 3327 px²/份,没有重叠。K 整页一个,同样的份额在任何一轮都一样大。
与故事的出入(自审后改的,按截图逐张看过)
- 概念层只在原地变形里画。 第 3 节写“变形与换轮中”都留余影;实际换轮时位置、面积与并入同时在动,一圈圈灰影叠成一片(f21 → f22 的截图),读不出谁在变。改成只在讲一遍的第 2 拍与“收到 ⇄ 给出”切换里画,换轮不画;透明度从 0.16 降到 0.14。静止时仍为零。
- 详情卡挨着圆,不贴图边。 第 4 节写卡贴在圆所在那一侧的图边;实际主水管半径约 146 px,卡贴到右侧图边时盖住了后刹与 Ture 发烧,引线拉过半张图。改为卡放在圆左右两侧里空地更大的那一侧,紧挨弹出后的圆(
hug: 'keep'),引线从圆的外缘一段直线连到卡最近的边,不再“出去再转向”(大圆上转折点落在圆里)。 - 详情卡里开着的问题放到最前,在收到的构成与两组逐轮小条图之前;小条图高 24 px。问题是卡里唯一能带人去作答的东西。
- 概要卡写“本轮进来 N 条 · 采用 M”,不只写采用的条数:暂缓与重复也算收到,只写采用会和卡上的“收到”对不上。
- 待落定的数写成细的“…”。 讲一遍里英雄数字右半边、侧栏两条的数在落定前起初画成等宽的方块,像被涂黑的字;改成细体省略号。
- 份额图例写成文字:“1 份 = 直径 60 px,24 份 = 292 px”。最初在底栏画 1、6、24 份三个缩小的圆,缩到 18 px 高以后看不出比例。
- 第 3 拍的注不越过左上角的说明行:master CI 在图的上缘,注最初落在说明文字上,注的候选位置改为只在说明行以下。
其余照第 3–4 节:三拍的时间表、讲一遍的触发与跳过、黑白与朱红的含义、留白虚线圈两态不变、换轮 0.7 / 0.42 秒、并入的一边缩一边挪进去、交互时序都没有改。讲一遍开始前把地址改成 ?frame=26(story 是 ?frame=17,即 f15),所以讲完刷新页面不会再讲。
没有做的。 草图把两态并排;这里只有一块原地变形的图,两态之间靠细圈与“收到 / 给出”切换,侧栏没有再放两张缩略的对照图。子层不画(composite 两周没有子层)。
6 验证
2026-10-28,本机无头 Chrome,1440×900,自起的 node 静态服务(深队列、不缓存)。
make check通过。node scripts/check-ix.mjs:composite 与 story 两个数据集下 13 页全部通过,本页 16 / 16(悬停、放宽 9 px、移开宽限与恢复、展开到底与标题面板切到“这一件”、Esc / 再点 / 点空白收回、Tab 与回车、触屏两下、连播中悬停不换轮、→ 换轮立即收起)。node scripts/shoot-forms.mjs --only morph,all --gpu --check all-sync:两个数据集下本页无报错,合页里本页报告所在帧、跟着顶栏选帧。composite 第一次跑合页失败在检查的最后一步(滚回腕上一瞥后它的 iframe 还在重载,[data-step="1"]为空),与本页无关,再跑两次都通过。npm ci && npm run site:build通过,dist/里有本页与previews/morph.webp。- 帧率(
--gpu):讲一遍全程 442 帧 59.9 fps,帧间隔 p95 16.8 ms,每帧脚本 0.22 ms(p95 0.3 ms);收到 ⇄ 给出两个方向各 1.0 秒都是 60 fps;换轮 60 fps;f16(23 件,最多的一帧)切换 60 fps。载入时算全部帧的排布:composite 约 100 ms,story 约 50 ms。 - 行为:顶层直接打开讲一遍,地址改成
?frame=26;带?frame=26打开静止;任意键跳到终态;prefers-reduced-motion直接到终态、不讲;讲完描边与注留着,第一次悬停后消失;变形中途(讲一遍 3.1 秒)与两态下墨量都是 64 份,第 1 拍长出中途是 56 份(有意不守恒,第 3 节)。 - 截图(本机 scratchpad,不入库):变形中途、落定、第 3 拍、悬停、展开 0.9 秒、story 变形中途与讲完、收到态。没有打开 Safari。