Archify Settled Flow 实战解析:以单次构建动画终结无限环绕,恢复可信的创作关系语义
【免费下载链接】archifyAgent skill for beautiful, verifiable architecture, workflow, sequence,>项目地址: https://gitcode.com/GitHub_Trending/arch/archify
本文围绕 Archify 开源仓库中 Visual Evolution Round 41 — Settled Flow 这份"可实施级研究决策"文档展开,完整讲解 Settled Flow 的设计动机、20 条精确实现契约、15 类失败模式与浏览器验收标准,并结合当前仓库中已落地的 template.html、cli.mjs 源码与 settled-flow.test.mjs 测试,说明"trace 动画只运行一次、随后永久回到创作态关系样式"这一机制的底层原理与验证方式。读完本文,你将理解如何在保持零依赖、无新增控件的前提下,让普通 trace 制品先完成一次短暂的环流动画,再安静地恢复到完全可读的静态拓扑。
一、问题本质:无限动画不只是观感问题,而是一次语义回归
Settled Flow 不是一次更柔和的审美调整。Round 41 文档通过运行时检查发现了一个可测量的语义缺陷:
- 普通 trace 边与节点使用无限(infinite)CSS 动画;
- 每一条参与动画的边都被套上
stroke-dasharray: 10 8; - 而创作契约中,
a-security关系应落定(settle)为5 5,a-dashed关系应落定为4 4; - 切到
Still(静止)只会停止时间轴,却把错误的10 8线型永久留在原地。
也就是说,当时的默认效果是在"替代语义"而不是"临时演示语义":无限环绕把作者精心定义的虚线节奏覆盖掉了,即使读者按下静止,错误的线型依然存在。当前仓库的 template.html 保留着创作契约的基准定义:
.a-default { stroke: var(--arrow); fill: none; } .a-emphasis { stroke: var(--arrow-emphasis); fill: none; } .a-security { stroke: var(--security-stroke); fill: none; stroke-dasharray: 5,5; } .a-dashed { stroke: var(--database-stroke); fill: none; stroke-dasharray: 4,4; }而更高优先级的 trace 选择器此前会把每条动画边都改成10 8。文档中记录的浏览器 readback 证实了这一点:
| 状态 | Security 计算后 dash | Async 计算后 dash |
|---|---|---|
| Live | 10px, 8px | 10px, 8px |
| Still | 10px, 8px | 10px, 8px |
| Authored contract | 5px, 5px | 4px, 4px |
结论很明确:Still当时只是暂停了时间,并没有恢复创作视觉语言。
二、目标体验:一次构建,永久安静
Settled Flow 的目标是让打开 trace 制品时只发生一次短暂的环流动画,然后永久返回作者定义的关系样式。文档给出的目标体验如下:
open trace artifact -> one staggered edge/node operating pass -> authored solid/security/async line language returns -> graph remains quiet -> reader-triggered Story/Route/Lens/Relationship motion still works关键约束是:不加运动模式、不加按钮、不加 schema 字段、不加预设、不加依赖、不引入第二套动画系统。Settled Flow 完全复用现有的data-animate钩子、Motion Governor 所有权模型与 WebM 导出管线,可以完全由 viewer/CSS 层自持(viewer/CSS-owned)。
三、方案权衡:为什么是 Settled Flow 而不是"再来一个新特性"
Round 41 文档给出了两个候选方案,并明确选择 A、跳过 B:
- Candidate A — Settled Flow(现在就构建):改进每一个启用 trace 的渲染器,修正一个可测量的语义问题,复用现有
data-animate、Motion Governor 与 WebM 管线。 - Candidate B — 另一个 Story 或视觉预设特性(跳过):Archify 已经拥有 Story Trail、Story Beats、Story Follow Camera、Story Director、Story Horizon、三套视觉预设、Route Journey、Semantic Flow、Relationship Pulse 以及读者可控的 Live/Still。再加一个面板或预设只会扩大功能表面积,却解决不了当前的无限循环与错误的落定关系样式。
两个候选的对比决策表如下:
| Axis | Settled Flow | Another feature/preset |
|---|---|---|
| Proven defect | Infinite loops and overwritten author dashes | None identified |
| Reach | All five trace renderers and WebM | One new surface |
| Reader value | Motion explains once, topology then reads cleanly | More discovery cost |
| Truth boundary | Restores existing authored classes | Risks new parallel semantics |
| Dependency/schema cost | None | Likely larger |
| Round 41 decision | Build | Skip |
"作用范围优先于功能表面积"是这份决策的核心取舍逻辑:同一个修复同时覆盖五个渲染器与 WebM 导出,而不是新增一处新的交互面。
四、当前工作树的三个关键证据
4.1 无限环绕的所有权问题
决策时点的 template.html 为 trace 边与节点分别挂载了infinite动画:
animation: archify-edge-flow 2.4s linear infinite; animation: archify-node-pulse 3.6s ease-in-out infinite;Signal Flow 与 Blueprint 预设只调整时长与质感,并不改变"无限迭代"这一契约本身;Signal Flow 还额外拥有一个无限六秒扫描(scan)。这意味着即使没有任何读者操作,页面也会永不停歇地消耗 CPU 与注意力。
4.2 作者线型语义被覆盖
如第一节所示,.a-security/.a-dashed的创作契约被高特异性的 trace 选择器覆盖为10 8。这正是"动画替代了语义"的证据:无限动画不是短暂地说明关系,而是永久改写了它。
4.3 强运动(Story 等)已经拥有正确的有限所有权
Motion Governor 早已把环境运动让位给 Story、Chapter、Route、Semantic Lens、Relationship Preview、Intent Trace、Focus 与 Legend 等信号。这些信号都是有限次、由读者发起的。Settled Flow 不得替换或重放它们,只修改无主的环境开场(ownerless ambient opening)。
4.4 导出边界已经就绪
静态 SVG/栅格导出使用serializeSvg();WebM 则生成一份全新序列化的 SVG 图片,并通过MediaRecorder录制六秒。因此,有限运动选择器可以只在 WebM 克隆体上显式启用,让录制得到一条"从构建到落定"的可重复时间线,而普通静态导出保持规范(canonical)状态。文档同时强调:WebM 导出不依赖 viewer 运行时是否已经落定。
五、行业参考:从五个来源中提取可转移的纪律
Round 41 对四个工具与一份规范做了比较,结论是"借纪律、不借实现"。以下思想对比来自文档本身,未引用外部链接:
Fireworks Tech Graph —— 构建、保持、守护源拓扑
其官方运动契约保证节点、标签、容器、标记几何与相机固定不动;路由按语义顺序绘制,完成后拓扑进入一段可读的驻留(hold)。其质量门禁保持源路径不可变,只插入瞬态运动装饰,而不是改写源真相。默认是一个固定 5.75 秒的包,包含构建阶段与可读的落定区间。
- Borrow:有限的语义顺序、可读的落定结果、不可变的源拓扑。
- Adapt:Archify 复用现有 CSS 标记与六秒 WebM 表面,不需要 Fireworks 的 GIF 渲染器或场景元数据。
- Skip:十二场景契约、Puppeteer/FFmpeg、motion-role schema、纯 GIF 分发、复制的签名特效、以及持续移动的落定轨道。
Structurizr —— 运动是有控件的故事
Structurizr 把动画定义为按顺序展示元素或关系的有序步骤,并提供前进/后退控件与键盘导航;其图片导出把动画步骤视为显式选项,而不是每个静态图的固有属性。
- Borrow:运动承担有边界的解释性工作;静态导出永远是显式的稳定产物。
- Adapt:Archify 的 Story 特性已经拥有刻意设计的步骤导航,环境 trace 只需引入并落定。
- Skip:新的步骤 UI 或导出模式。
LikeC4 —— 场景运动与持久模型真相分离
LikeC4 的动态视图用有序交互、并行步骤、备注与导航描述某个特定用例,而不污染持久模型。
- Borrow:瞬态解释不得修改持久关系模型。
- Adapt:把 Archify 的动画状态视为 viewer 专属;创作类与规范 SVG 始终具有权威性。
- Skip:新的动态视图 DSL、备注 schema 或并行故事创作。
D2 —— 循环有理解成本
D2 文档指出动画 SVG/GIF 适合小构图,并警告过多画板会迷惑读者或迫使他们等完一个循环。
- Borrow:自动运动要足够短,一遍就能看懂。
- Adapt:一个拓扑、一次有限运动通路、然后静止。
- Skip:画板组合与重复的轮播式动画。
W3C —— 自动运动必须可抑制
WCAG 的 Pause, Stop, Hide 指引要求能够暂停或停止合格的自动移动内容;WAI 轮播模式同样把自动旋转视为受控的读者状态。
- Borrow:Still 与 reduced motion 保持权威性。
- Adapt:自动结束环境运动比仅仅增加一个暂停按钮更强。
- Skip:自动重放、悬停重启或第二套运动偏好。
汇总:Borrow / Adapt / Skip
| Decision | Round 41 contract |
|---|---|
| Borrow | 一次构建/运动通路后接一个可读的驻留。 |
| Borrow | 守护作者路径、标记、线型变体、节点、标签与相机。 |
| Borrow | 让刻意的 Story 运动保持读者可控且有限。 |
| Adapt | 复用现有data-animate钩子与 Motion Governor 所有权。 |
| Adapt | 让六秒 WebM 克隆体选择加入同一条有限时间线。 |
| Adapt | 只封顶动画延迟,绝不改变创作图序或身份。 |
| Skip | 新控件、预设、依赖、schema、GIF 渲染器或场景 DSL。 |
| Skip | 无主的无限边、节点或背景扫描循环。 |
| Skip | 在运动结束后重写 security/async dash 语义。 |
六、精确实现契约:20 条不可妥协的规则
Round 41 给出了可以直接照做的实现清单,逐条列出如下:
- 普通启用 trace 的页面只在 HTML viewer 上获得
running -> settled环境状态。 - 每条边与节点的环境动画恰好使用一次迭代。
- Signal Flow 的背景扫描也只运行一次,并淡出到无残留。
- trace 选择器不得在作者边上永久设置
stroke-dasharray或stroke-dashoffset。 - 通路落定时,
a-default与a-emphasis回到实线,a-security回到5 5,a-dashed回到4 4。 - 动画关键帧可以临时可视化流动,但必须以底层的作者计算样式结束。
- 共享渲染器的动画延迟被封顶,使每个受支持的证明都能在现有六秒 WebM 窗口内落定。
- 封顶只改变
--step;图/源顺序、Story 顺序、ID 与关系语义均不受影响。 - Motion Governor 在每个页面生命周期内至多启动一次环境通路。
- Still、reduced motion、隐藏文档、嵌入、分享播放或更强的语义所有者都会落定/抑制环境运动,且之后不再重放。
- 从 Still 返回 Live 不会重放环境开场。
- 清除 Focus/Route/Lens/Story 所有权不会重放它。
- Story、Route、Lens、Relationship、Intent、Chapter 与相机行为保持各自现有的有限契约。
- Live/Still 控件仍是唯一运动控件;不引入新行、徽标、开关或存储键。
- 普通嵌入保持安静,除非请求其已有的显式有界 Story。
- 静态 SVG、PNG、JPEG、WebP、打印与剪贴板输出保持规范。
- WebM 序列化显式地让其克隆体选择加入一次有限环境通路,并在现有六秒停止前捕获一个落定驻留。
- WebM 导出不依赖 viewer 已经落定的运行时阶段。
- 没有
meta.animation: trace的静态制品不获得任何运动状态或可见控件。 - 不改动任何 schema、渲染器几何、布局、标记、关系 ID、依赖或 JSON 创作面。
七、源码印证:当前仓库中的 Settled Flow 落地实现
决策文档写于 2026-07-20,当前仓库中该方案已经落地,以下实现事实均可直接核对。
7.1 有限迭代的 CSS 契约
在 template.html 中,环境动画以html[data-ambient-motion="running"]为前置条件,且迭代次数为1:
/* Optional trace animation, enabled only by meta.animation = "trace". The ordinary viewer performs one ambient pass and then restores the authored solid/security/async line language. WebM samples the same authored geometry into an explicit canvas timeline. */ html[data-ambient-motion="running"] svg[data-animation="trace"] [data-animate="edge"] { animation: archify-edge-flow 2.4s linear 1; animation-delay: calc(var(--step, 0) * 160ms); } html[data-ambient-motion="running"] svg[data-animation="trace"] [data-animate="node"] { transform-box: fill-box; transform-origin: center; animation: archify-node-pulse 3.6s ease-in-out 1; animation-delay: calc(var(--step, 0) * 160ms); }注意两个关键设计:其一,running状态是显式挂载在<html>根节点上的门闩属性,动画只有在"正在运行"阶段才生效,落定后整条规则自然失效;其二,运行期规则中不包含stroke-dasharray/stroke-dashoffset,临时虚线完全由@keyframes archify-edge-flow内部承担(见 template.html):
@keyframes archify-edge-flow { 0% { stroke-dasharray: 10 8; stroke-dashoffset: 54; opacity: 0.42; } 88% { stroke-dasharray: 10 8; stroke-dashoffset: 0; opacity: 1; } 99.9% { stroke-dasharray: 10 8; stroke-dashoffset: 0; opacity: 1; } 100% { stroke-dashoffset: 0; opacity: 1; } }100%帧只声明stroke-dashoffset: 0; opacity: 1;,刻意回到底层创作样式——这正是契约第 6 条"关键帧以底层作者计算样式结束"的实现形态。Signal Flow 的无限六秒扫描同样被改为单次并淡出(@keyframes archify-signal-scan的100%帧opacity: 0)。
7.2 运行时所有权:一次启动、永不重放
在 template.html 中,运行时以三个函数闭环实现"至多一次":
startAmbient():用ambientStarted布尔门闩保证每个页面生命周期只启动一次;将当前 DOM 中所有[data-animate="edge"], [data-animate="node"]收集进ambientPending集合;随后在<svg>上挂载animationend/animationcancel捕获监听,并把根节点置为data-ambient-motion="running"。onAmbientBoundary(event):每收到一个动画结束/取消事件就从ambientPending中删除对应目标;当集合为空时调用settleAmbient('complete')。settleAmbient(reason):清空ambientPending、卸载监听,把根节点置为data-ambient-motion="settled"并记录data-ambient-settle-reason(如complete、suppressed、empty)。
由于ambientStarted一旦置真就不再复位,Still -> Live 切换、Focus/Story 清理都不会重放环境开场;paused、强语义owner、data-embed等路径则直接调用settleAmbient('suppressed')。测试文件 settled-flow.test.mjs 专门断言了这些门闩与监听器的存在,并确认没有任何setInterval或 scroll 监听与 ambient 相关。
7.3 延迟封顶:只动--step,不动语义身份
五个渲染器共享的animateAttr实现位于 cli.mjs:
export function animateAttr(meta, kind, step) { if (meta.animation !== 'trace') return ''; // Ambient trace must finish inside the fixed six-second WebM capture. The // cap affects visual delay only; authored order and semantic identity stay // untouched in the JSON, DOM, Story, and relationship contracts. const safeStep = Number.isFinite(step) && step >= 0 ? Math.min(12, Math.floor(step)) : 0; return `>390px 宽度下现有 Live/Still 控件至少保持 44px,页面无横向溢出。 移动端环境运动恰好落定一次。 普通嵌入从静态/落定开始;显式?play=1的 Story 仍播放一次并落定。 导出与无障碍
- reduced-motion CSS/运行时保持作者的静态拓扑。
- 下载 SVG 保持规范,不含任何 viewer 阶段状态。
- 支持的浏览器上,简短的 WebM smoke 返回非空 blob。
- 即使 live viewer 已经落定,WebM 时间线也从头开始运动。
- 打印与栅格导出保持完整且静止。
- 不引入任何应用来源的控制台警告或错误。
这 16 条可以直接转化为手动验收或端到端冒烟用例,配合 motion-governor.test.mjs 等既有测试共同守护运动契约。
十一、决策结论与可迁移的纪律
Round 41 的最终决策是:现在就实现 Settled Flow。
从 Fireworks Tech Graph 学到的可迁移教训,不是样式的数量或 GIF 管线,而是这样一条纪律:一次有限的语义构建,接一个清晰可读的落定拓扑,同时守护源几何与意义。Archify 以更干净的方式吸收了它——五个渲染器共享一套零依赖的 viewer 契约、复用现有读者可控交互与 WebM 导出、并精确恢复作者的关系语言。
对普通读者而言,最终体验是:打开 trace 制品 → 一次错峰的边/节点运动通路 → 创作态实线/Security/Async 线型回归 → 拓扑保持安静;而 Story、Route、Lens、Relationship、Intent 等由读者触发的有界运动完全不受影响。对开发者而言,Settled Flow 证明了一条可复用的设计原则:默认动画应该"解释一次、然后退出",永远不要把瞬态演示固化成对创作真相的改写。
【免费下载链接】archifyAgent skill for beautiful, verifiable architecture, workflow, sequence,>
项目地址: https://gitcode.com/GitHub_Trending/arch/archify
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考