Skip to content

空间类形式的打磨:原版树图与 A 空间排布 ​

状态:2026-10-15 的原型打磨记录,不是产品规范,也不选定方案。记录写于第一次自由运行(free-composite-2026-10-15)打磨出的演示数据,2026-10-15 晚按第二次自由运行(free-20261015-161501)的演示数据更新了引用:事项、选项与计数换成新数据;性能数字与截图是在旧数据上测得、拍下的,没有重做。数据以 composite 演示集(Jonas 的两周,29 帧)为准,story 数据集(林苒,37 帧,有子层与合并)同样能跑。回应只存在本页内存里,不写回演示数据,也不调用模型。

两种形式都围绕产品方向的四件事打磨:先看到值得关注的事和它为什么在这里,先要点后细节,变化可追溯,保存、Agent 处理确认和外部行动结果分开说。

共用底座 ​

两种形式共用新文件 prototype/variants/spatial-kit.mjs,没有改动 engine、motion、shared、respond 或 explore。

  • 措辞:本人的输入写成动作句(“在 GitHub 上批准了 #13591”“在问答站回复了 Gerda”),署名统一为人物名;回复只有在 feedback.ask 对得上时才算回答了某个问题,否则写“记在「某事」上,那里的问题仍开着”。正文用轻量 markdown 渲染,预览用去掉标记的单行文字。
  • 折叠:根层里 1 份、没有问题、没有子层的事项满 3 件就合成一块“另有 N 件小事”,面积等于份额之和,排在所有单独事项之后。
  • 回应:包一层 respond.mjs 的 createResponseStore,按事项与问题 id 查找,所以 Agent 改写事项后回执仍在。作答后立刻显示“已保存,等 Agent 下一轮整理”;推进到下一帧显示“Agent 已在 HH:MM 的整理中收到”;合并或修改是否真的发生,要看之后的版本。随时可以撤销。
  • 动画:createFlipBoard 把每个格子拆成形状和正文两层。形状用 transform 平移缩放,正文保持终态排版,只平移并按形状大小裁切,所以字形不会被拉伸;没变的格子不动;中途打断时从当前视觉位置继续;prefers-reduced-motion 时直接到终态。flipList 处理左栏、输入栏这类列表。
  • 布局:a-layout.mjs 新增 layoutFill,用同一套条带搜索把事项和留白铺满整块板,给原版使用;同时修了 layoutPapers 的一个缺陷:事项自带的 weight 字段("high"/"low")曾混进代价计算得到 NaN,导致剪枝失效、12 件以内时退化成整排横条。

切帧时同步执行的脚本:原版从 motion.mjs 时期的 94–128 ms 降到 12–30 ms;A 为 12–23 ms(headless Chrome,1440×900)。

原版树图 ​

换轮与作答的动画、悬停与展开(第三轮标准)另记在 tree-motion.md;下文的信息承载仍有效,与它不一致处以它为准。

场景:坐在电脑前,整体掌握这两周的局面,顺手处理工作评审。

承载的回应:approve。#13350、#13596 这类 PR 评审的格子里直接显示 PR 标题和“批准 / 要求修改”,详情和概览里也能作答;其他类型的问题(选择、定时间、稍后)在详情里用 respond.mjs 的完整控件作答。

信息承载

  • 根层事项铺满整块板,留白是最后一格;1 份的问题格子不会被挤成细条(布局改用 layoutFill)。第 27 帧根层 14 件里有 6 件只占 1 份,其中不带问题的 4 件合成“另有 4 件小事”,标题按本轮新增在前列出。旧数据这一帧是 35 件里 30 件只占 1 份、24 件合成小事块,折叠是按它设计的;新数据根层短得多,规则不变,记录保留作为设计理由。
  • 左侧输入栏按流分组:“你 · Jonas”在最前,每条是动作句加“接到哪件事”;工作、家庭、生活、社区、订阅各组只展开被采用的输入,其余折成“还有 N 件”。
  • 右侧默认是概览:工作评审列表(可直接批准)、其他问题(逾期标红)、这一轮你在原处做了什么。计数只算还没回应的问题。
  • 详情依次是:作答卡、为什么在这里、依据(两行预览,点开看 markdown 原文)、来源处的回应、本轮变化、这件事的两周版本(份额条,可跳帧)和时间。

交互清单

  • ←/→ 逐帧,空格播放,点时间轴或章节分段跳转,0.5×/1×/2× 倍速,重播过渡,慢动作(×3),对比起点。
  • 点格子打开详情;hover 显示“详情 ›”;格子被裁切或很小时,hover 弹出完整标题、问题和摘要。
  • hover 输入栏的条目或概览里的问题,对应格子描边。
  • 格子内直接批准或要求修改;详情里 A 批准、R 要求修改;U 撤销最近一次;作答后格子内收成一行回执。
  • 点“另有 N 件小事”放大成独立的一块板,面包屑或 Esc 返回;有子层的格子可以下钻。
  • Tab 逐格移动,Esc 依次关闭面板、返回上一层。

动画清单

  • 切帧 320 ms ease-out:位置变化的格子平移,份额变化的格子长大或缩小;内容改了的格子新旧正文交叉淡出。
  • 新事项从目标位置 60% 大小处淡入,撤下的事项原地收缩淡出,合并的来源飞进目标格子(story 数据集)。
  • 下钻、放大小事块 460 ms,经由锚点格子缩放;慢动作把所有时长乘 3。
  • 回执、面板、toast 用 160–220 ms 的淡入;reduced-motion 下没有动画。

截图(本地,.local/ 不入库):.local/polish-spatial/original/

  • 静态帧:frame-03.png、frame-10.png、frame-18.png、frame-22.png、frame-26.png
  • 切帧连拍(25→26,每 80 ms 一张,共 6 张):sequence-25-26-000ms.png 至 sequence-25-26-400ms.png
  • 作答:answer-0-before.png、answer-1-saved.png、answer-2-next-frame.png、answer-3-received-detail.png、answer-4-undone.png
  • 详情与原文:detail-copper.png、detail-copper-scrolled.png、event-markdown.png、inputs-rest-open.png
  • 小事块:tail-open.png、tail-closed.png
  • story 数据集:story-7.png、story-20.png、story-36.png、story-merge-mid.png、story-merge-end.png、story-dive-mid.png、story-dive-end.png
  • 其他:narrow-1024.png、narrow-390.png、reduced-26.png

未解决

  • 条带布局里一件事的份额一变,同一条带和后面条带的格子都会重排,切帧时移动的格子偏多;还没有跨帧保持位置的约束。
  • 1 份的问题格子在窄列里标题仍要截断,要靠 hover 卡片读全。
  • 内容变了又在移动的格子,前 80–160 ms 新旧两段正文会短暂叠在一起。
  • 正文裁切用 clip-path 动画,主线程要重绘;headless 下测得的长帧来自软件栅格,没法据此判断真机 GPU 下是否足够顺。
  • 手机宽度不是这种形式的场景,只保证不横向溢出。

A 空间排布 ​

场景:在桌前,生活里几件急事需要当场二选一,例如猫的药量(打给诊所 / 先观察)和车道下的主水管(整根挖开换 / 免挖穿新管)。

2026-10-20 按第三轮的标准重做了动画与交互,见 a-motion.md:换轮与作答走节拍表,回执跟着条目走,悬停与展开共用 motion/ix.mjs;下面的交互与动画清单里,纸片的全文浮层、toast 与 320 ms 一齐移动的切帧已由它取代。

承载的回应:choose,以及“稍后”(defer)。左栏的问题按份额和是否逾期排序,同等条件下 choose 优先。approve、定时间、回一句也能在卡片里完成。

信息承载

  • 左栏“现在要你定”:只给最急的 2 个问题大卡(窗口高度 ≥ 980 px 时给 3 个),卡上是问题、所属事项、截止或逾期、份额和选项(推荐项实心);其余收成“另有 N 个问题开着”,点开是一行一个的紧凑列表。
  • 回答过的问题留在原位,收成一行回执;选“稍后”的问题移到“稍后再看”,把位置让给下一个问题,到点后回来。
  • 左栏下部“这一轮你在原处做了”:动作句、对象标题、接到哪件事;story 数据集没有本人输入标记,这一节不显示。
  • 右侧纸片面积等于份额,空着的桌面就是未分配。小事合成一叠“另有 N 件小事”。大纸片的空白处补上“为什么在这里”。已有大卡的问题,纸片上不再重复问题文字,用 hover 联动指回卡片。
  • 详情面板:同一张作答卡、为什么在这里、依据(预览 → markdown 原文)、来源处的回应、这件事的版本(可跳帧)、原始 JSON。

交互清单

  • 卡片:点选项作答;“回一句”展开输入框(Enter 发送,Esc 收起);“◷ 稍后”展开 1 小时后 / 2 小时后 / 明早 09:00。焦点在卡片内时,选项上出现 1、2… 角标,按数字键直接选择。作答后焦点停在这张卡的“撤销”上;U 撤销最近一次;toast 里也有撤销。
  • “另有 N 个问题开着”展开紧凑行,点一行把它展开成卡片。
  • 纸片:点开详情;hover 时页脚出现“看详情 ›”;太小或被裁切的纸片 hover 220 ms(键盘聚焦立即)后在旁边弹出全文。卡片、紧凑行、本人动作与纸片双向描边联动;问题在小事堆里时,描边落在那一叠上。
  • “另有 N 件小事”铺开成等大纸片,面包屑或 Esc 收回;有子层的纸片“N 个子项 ↗”下钻(story 数据集)。
  • 详情面板打开时接过键盘焦点,Esc 关闭后焦点回到原来的纸片或卡片;在面板里打开的“稍后”或输入框只出现在面板里。
  • 时间:←/→、空格播放、拖动或点时间轴(滑块支持 Home/End/PageUp/PageDown)、对比起点(键盘可操作的列表框)、慢速、重播过渡。

动画清单

  • 纸片切帧 320 ms ease-out,与原版同一套形状 / 正文两层的 FLIP;新纸片从 60% 大小处淡入,撤下的原地收缩淡出,story 的合并来源飞向目标纸片。
  • 铺开小事和下钻 460 ms,经由锚点纸片缩放;板面裁切在桌面范围内,飞出的纸片不会盖住左栏和时间轴。
  • 左栏 280 ms:留下的卡片滑到新位置,变高的卡片逐步露出新内容;离开的卡片先在原地淡出(112 ms),新卡片随后进入,两段文字不会叠在一起。
  • 详情面板 240 ms 从右侧滑入,toast 220 ms,时间轴拇指 200 ms;慢速 ×3;reduced-motion 下切帧没有动画。

截图(本地):.local/polish-spatial/a/

  • 静态帧:frame-04.png、frame-12.png、frame-18.png、frame-22.png、frame-26.png、frame-28.png
  • 切帧连拍(25→26,每 80 ms 一张,共 6 张):sequence-25-26-000ms.png 至 sequence-25-26-400ms.png
  • 作答:answer-0-before.png、answer-1-saved.png、answer-2-next-frame.png、answer-3-undone.png;键盘:keyboard-0-focus.png、keyboard-1-answered.png
  • 稍后与长尾问题:later-0-options.png、later-1-snoozed.png、later-2-folded-open.png
  • 详情:detail-cat.png、detail-cat-scrolled.png、detail-cat-versions.png、event-own.png、event-own-all.png
  • 小事铺开:tail-mid.png、tail-open.png、tail-closed.png;hover:peek.png、hover-card-link.png
  • story 数据集:story-7.png、story-20.png、story-36.png、story-merge-mid.png、story-merge-end.png、story-dive-mid.png、story-dive-end.png
  • 其他:narrow-820.png、narrow-390.png、reduced-26.png
  • 打磨前的基线:.local/polish-spatial/before/a.png

未解决

  • 大卡数量只看窗口高度,没有按卡片实际高度计算;回答过的卡片也占位,所以答过一题后第三张卡可能把“另有 N 个问题”挤到左栏可见范围之外,需要滚动。
  • 演示数据不会因为本页的回答而变化,回答过的卡片会一直留着“已收到”的回执,直到 Agent 改登记新的问题。
  • 详情面板盖住桌面右侧,打开时右侧纸片点不到。
  • layoutPapers 在 12 件以内两个方向都穷举(约 2–4 ms),更多时只试一个方向;纸片跨帧的位置稳定性同样没有专门约束。
  • “稍后”只在本页生效,到点后问题回到列表,但没有提醒。

Safari 检查(2026-10-15) ​

合页 all.html 做完后,在 Safari 27 里实际打开看过,并用离屏 WebKit(WKWebView,与 Safari 同一引擎)按 1440×900 逐节截图,和 Chrome 无头截图并排对比;顶栏切到 f05 后再截一遍。原版树图与 A 空间排布与 Chrome 一致,只有个别文字换行位置不同,没有需要修的差异。