首页
/ OpenMontage HyperFrames 实战:用 GSAP 确定性时间轴打造 AI 目标检测跟踪框(ai-tracking-box)动画

OpenMontage HyperFrames 实战:用 GSAP 确定性时间轴打造 AI 目标检测跟踪框(ai-tracking-box)动画

2026-09-07 14:49:15作者:胡唯隽

导读:本文深入解析 OpenMontage 仓库中 .agents/skills/hyperframes-animation/rules/ai-tracking-box.md 这条原子动画规则——如何在 HyperFrames 合成里实现一个带黄色 L 型角标的"AI 目标检测跟踪框",让目标物沿正弦轨迹移动、边界框逐帧贴合、置信度标签实时跳动,从而在营销片、产品演示、AI 概念片中模拟出真实的实时检测观感。读完你将掌握其 HTML/CSS/GSAP 完整实现、全部可调参数的选择方法论,以及它如何在 HyperFrames 确定性逐帧渲染契约下保持"同一输入时间必然渲染出同一帧画面"。

一、规则定位:一条用于"检测感"的原子动画配方

ai-tracking-box 是 OpenMontage 中 hyperframes-animation 技能下的原子运动规则之一。该技能约定:大多数动效场景不必从零堆代码,而是从 rules-index.md 中挑选 2~4 条原子规则,用一条 paused 的 GSAP 时间轴拼合完成。ai-tracking-box 在 rules-index 中被归入 "Layout & Network" 类别,tags 为 ai, tracking, bounding-box, detection, corner, ml,其职责是:

AI 检测覆盖层——黄色 #facc15 L 型角标 + 置信度标签(在 95~99% 区间波动),跟随目标沿正弦弧线移动;边界框位置每帧由目标位置推导(绝不与目标分离单独补间)。

它的典型画面语义是:画面中央是一个产品吉祥物 / 目标字形,一段时间的"识别扫描"后,一个黄色 L 角标方框像实时目标检测算法那样"锁定"它,顶部浮出 人形 97% 之类的置信度读数——这是自动驾驶 HUD、安防 CV、ML Demo 等体裁的通用视觉语言。

该文件位于 .agents/skills/hyperframes-animation/rules/ai-tracking-box.md,与它同级的还有 viewport-change.md(虚拟相机)、multi-phase-camera.md(多段相机)、sine-wave-loop.md(呼吸/闲置微动)等规则,常被组合成"识别→锁定→推近"的完整叙事。

二、工作原理:三条核心机制

规则文档将实现拆为三个层面:

  1. 位置与尺寸来自正弦 + 漂移:边界框的坐标 (x, y) 与尺寸 (w, h) 均由组成时间的正弦函数推导。目标沿正弦弧线往复运动(x 用余弦、y 用正弦可得到椭圆轨迹),边界框尺寸做小幅抖动,模拟检测器持续"重算"而非机械静止。
  2. 4 个 L 型角标作为覆盖层:每个角标是一个 <div>,用"两侧边框"拼出 L 形状,贴在边界框四角之上——这是"检测框"体裁的签名视觉,与普通全边框 UI 框刻意区分。
  3. 置信度标签:可选的标签块位于左上角之上,显示类别名与百分比,并在紧窄区间内持续闪烁,模拟"实时推理"。

全部运动由 GSAP 时间轴驱动,这是为了让 HyperFrames 能确定性 seek:渲染器按时间取帧,不支持 CSS 动画与时间轴并行推进的播放式语义(详见下文"确定性契约")。

三、HTML 骨架:边界框包裹目标

规则文档给出的 HTML 结构以 data-* 属性声明组合与时间信息,这与 hyperframes-core 对合成根节点的约定一致(详见 data-attributes.mddata-composition-id 必须是唯一 ID 且与 window.__timelines 注册键一致,data-width/data-height 声明帧尺寸,data-duration 声明渲染时长,data-track-index 声明所在轨道)。

<div
  class="scene"
  id="track-scene"
  data-composition-id="track-scene"
  data-start="0"
  data-duration="5"
  data-track-index="0"
>
  <!-- 背景 —— 可以是产品 mockup、主视觉图等 -->
  <div class="bg">
    <div class="bg-content">{Brand}</div>
    <div class="bg-mascot" id="mascot">{targetGlyph}</div>
  </div>

  <!-- 跟踪框包裹目标 -->
  <div class="track-box" id="track-box">
    <div class="corner tl"></div>
    <div class="corner tr"></div>
    <div class="corner bl"></div>
    <div class="corner br"></div>
    <div class="label" id="label">{targetGlyph} {LABEL} · {confidence}%</div>
  </div>
</div>

要点拆解:

  • #mascot 是被跟踪的"目标"字形(背景中的大号角色/图标),.track-box 是覆盖其上的检测框容器,角标与标签都是它的子元素,天然随框移动;
  • 所有占位符({Brand}{targetGlyph}{LABEL}{confidence} 等)在正式合成中由变量注入,与 hyperframes-core 的 variables-and-media 机制配套;
  • data-duration="5" 意味着这是一个 5 秒的合成,内部时间轴由规则下文的阶段参数切分。

四、CSS:角标怎么"长出"两个边、标签怎么贴合

规则文档提供了完整的可运行样式,其视觉策略是:背景用暗色径向渐变让黄色标记弹出;.track-box 为绝对定位、尺寸与坐标完全交给 GSAP onUpdate 逐帧写入(因此 will-change 声明 transform, width, height,并关闭指针事件,作为纯装饰覆盖层)。

.scene {
  position: relative;
  width: 100%;
  height: 100%;
  background: radial-gradient(ellipse at center, {bgInner} 0%, {bgOuter} 70%);
  font-family: {font};
  overflow: hidden;
}
.bg {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  gap: 60px;
}
.bg-content {
  position: absolute;
  top: 120px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 80px;
  font-weight: 900;
  color: {bgTextColor};
  letter-spacing: 12px;
  text-transform: uppercase;
}
.bg-mascot {
  position: absolute;
  font-size: 240px;
  line-height: 1;
}

.track-box {
  position: absolute;
  /* 位置 + 尺寸由 GSAP onUpdate 写入 */
  pointer-events: none;
  will-change: transform, width, height;
}
.corner {
  position: absolute;
  width: 48px;
  height: 48px;
}
.corner.tl {
  top: -8px;
  left: -8px;
  border-top: 6px solid {detectionYellow};
  border-left: 6px solid {detectionYellow};
}
.corner.tr {
  top: -8px;
  right: -8px;
  border-top: 6px solid {detectionYellow};
  border-right: 6px solid {detectionYellow};
}
.corner.bl {
  bottom: -8px;
  left: -8px;
  border-bottom: 6px solid {detectionYellow};
  border-left: 6px solid {detectionYellow};
}
.corner.br {
  bottom: -8px;
  right: -8px;
  border-bottom: 6px solid {detectionYellow};
  border-right: 6px solid {detectionYellow};
}
.label {
  position: absolute;
  top: -56px;
  left: -8px;
  padding: 8px 16px;
  background: {detectionYellow};
  color: {labelTextColor};
  font-family: {monoFont};
  font-size: 24px;
  font-weight: 800;
  letter-spacing: 2px;
  border-radius: 6px;
  white-space: nowrap;
}

设计意图注释:

  • 每个 .corner48×48px 的正方形,只在相邻两侧设 6px 边框,并向外偏移 -8px,使角标"咬住"方框四角而非覆盖在边界线上;
  • .track-box 在 GSAP 未写入前只依赖 CSS 默认定位,代码里用注释明示"位置 + 尺寸由 GSAP onUpdate 写入",避免作者手写死值造成冲突;
  • .label 向上悬出 56px、左对齐到 -8px,用等宽字体 + 800 字重 + 2px 字距强化"机器读数"的暗示;white-space: nowrap 防止置信度刷新时换行跳动。

五、GSAP 时间轴:入口弹跳 + 逐帧 onUpdate 的跟踪阶段

规则文档给出核心脚本(GSAP 需按项目资源策略内联或本地化引入——HyperFrames 的确定性契约要求渲染关键资源不得在渲染时发起网络请求,详见 determinism-rules.md):

<script>
  window.__timelines = window.__timelines || {};
  const tl = gsap.timeline({ paused: true });

  const box = document.getElementById("track-box");
  const mascot = document.getElementById("mascot");
  const label = document.getElementById("label");

  // 初始状态 —— 框不可见,待淡入
  gsap.set(box, { opacity: 0, scale: ENTRY_SCALE });

  // 阶段 1 —— 检测框入场(淡入 + 缩放到 1)
  tl.to(
    box,
    {
      opacity: 1,
      scale: 1,
      duration: ENTRY_DUR,
      ease: `back.out(${ENTRY_BOUNCE})`,
    },
    ENTRY_START,
  );

  // 阶段 2 —— 持续的 "AI 跟踪":框与吉祥物沿正弦路径同步移动
  const SCREEN_CENTER = { x: COMP_WIDTH / 2, y: COMP_HEIGHT / 2 };
  // DRIFT_X / DRIFT_Y —— 目标振荡幅度 (px)
  // SIZE_BASE / SIZE_VAR —— 框的均值尺寸 + 逐帧抖动幅度 (px)
  // SIZE_FREQ_MULT —— 跟踪相位上的倍率,让框 "呼吸" 与漂移不同拍
  // CYCLES —— 整个 TRACK_DUR 内的完整振荡次数
  // TRACK_DUR —— 跟踪阶段时长 (s)
  // TRACK_START —— 跟踪阶段开始时刻 (s)
  // CONFIDENCE_MEAN / CONFIDENCE_VAR —— 置信度闪烁的中心值 + 半区间
  // CONFIDENCE_FREQ_MULT —— 置信度相对漂移的闪烁速度倍率

  const tracking = { p: 0 };
  tl.to(
    tracking,
    {
      p: Math.PI * 2 * CYCLES,
      duration: TRACK_DUR,
      ease: "none",
      onUpdate: () => {
        // 目标位置(吉祥物沿更宽的弧线移动)
        const mx = SCREEN_CENTER.x + Math.cos(tracking.p) * DRIFT_X;
        const my = SCREEN_CENTER.y + Math.sin(tracking.p) * DRIFT_Y;
        mascot.style.position = "absolute";
        mascot.style.left = `${mx - MASCOT_SIZE / 2}px`;
        mascot.style.top = `${my - MASCOT_SIZE / 2}px`;

        // 框尺寸小幅振荡(尺寸置信度变化)
        const w = SIZE_BASE + Math.sin(tracking.p * SIZE_FREQ_MULT) * SIZE_VAR;
        const h = SIZE_BASE + Math.sin(tracking.p * SIZE_FREQ_MULT + Math.PI / 2) * SIZE_VAR;

        // 框位置以吉祥物为中心
        box.style.width = `${w}px`;
        box.style.height = `${h}px`;
        box.style.left = `${mx - w / 2}px`;
        box.style.top = `${my - h / 2}px`;

        // 置信度标签在 [CONFIDENCE_MEAN ± CONFIDENCE_VAR] 内波动
        const confidence = Math.round(
          CONFIDENCE_MEAN + Math.sin(tracking.p * CONFIDENCE_FREQ_MULT) * CONFIDENCE_VAR,
        );
        label.textContent = `${TARGET_GLYPH} ${LABEL_TEXT} · ${confidence}%`;
      },
    },
    TRACK_START,
  );

  window.__timelines["track-scene"] = tl;
</script>

这段代码有两个高价值实现细节:

其一,用"相位代理对象"驱动多元素。 GSAP 只补间一个普通的 { p: 0 } 代理对象,让它从 0 线性推进到 Math.PI * 2 * CYCLES,真正的"运动"全部发生在 onUpdate 回调里——吉祥物位置、框尺寸、框位置、置信度标签在同一次回调内被统一重算。这与 hyperframes-animation 的"单条时间轴、多种元素在一个驱动相位上同步"的通用手法一致,可参考 .agents/skills/hyperframes-animation/SKILL.md 中"tween on a proxy object → onUpdate"的其它用例。

其二,确定性 seek 友好。 代理值 tracking.p 只是 tl.time() 的单调映射,不依赖任何时钟或累计状态;渲染器无论正播、倒播、跳帧采样,同一时间点得到的就是同一个 p。这正是 determinism-rules.md 强调的"每帧可复现"契约:不用 Date.now()/performance.now()、不用未播种的 Math.random()、不用 CSS 动画驱动渲染关键运动、不用 repeat: -1 无限循环。框体的 opacity/scale 入场采用 GSAP 补间而尺寸/坐标采用 onUpdate 直写,二者都在时间轴内,seek 时均可正确还原到任意中间帧。

六、参数选择手册:从"能用"到"有检测味"

规则文档的最大价值在于给了每个常量完整的调参知识(范围 / 效果 / 约束 / 参考值)。以下按原文完整展开:

入场参数(阶段 1)

  • ENTRY_SCALE — 框弹入前的起始缩放
    • 范围:0.5–0.9;约束:必须 < 1(框是"放大就位");参考值 0.7
    • 效果:低端 = 更强的弹出感/"咔哒锁焦";高端 = 轻微显现
  • ENTRY_DUR — 淡入 + 放大时长(秒)
    • 范围:0.3–0.8s;约束:应在 TRACK_START 前结束;参考值 0.5
    • 效果:低端 = 干脆利落的权威锁定;高端 = 柔和、观察式的呈现
  • ENTRY_START — 入场补间开始时刻(时间轴绝对秒数)
    • 范围:通常 0–2s;约束:ENTRY_START + ENTRY_DUR ≤ TRACK_START;参考值 0.5
    • 效果:晚开始 = 先让观众看到目标,AI 再"发现"它;早开始 = AI 从一开始就在注视
  • ENTRY_BOUNCE — 传给 back.out(...) 的回弹系数
    • 范围:1.2–2.5;约束:坚持 back.out 族——elastic 读作卡通感、power 读作扁平;参考值 1.4
    • 效果:低端 = 轻微过冲;高端 = 夸张的吸附感(读作"激进锁定")

跟踪参数(阶段 2)

  • TRACK_START — 连续跟踪开始时刻(秒)
    • 范围:≥ ENTRY_START + ENTRY_DUR;约束:TRACK_START + TRACK_DUR ≤ 合成总时长;参考值 1.0
    • 效果:与入场留有间隔 = 强调停顿;无间隔 = 无缝的"锁定即跟随"
  • TRACK_DUR — 跟踪阶段时长(秒)
    • 范围:2–8s;约束:至少容纳一个完整 CYCLE 才读得出振荡;参考值 4.0
    • 效果:短 = "快速扫过";长 = "持续观察"
  • CYCLES — 目标在 TRACK_DUR 内完整正弦振荡的次数
    • 范围:0.5–3;约束:CYCLES / TRACK_DUR 即漂移的有效 Hz,需 < ~0.6 Hz 否则产生运动模糊;参考值 1.5
    • 效果:低 = 慵懒漂移;高 = 抖动的/多动的目标
  • DRIFT_X / DRIFT_Y — 目标绕屏幕中心振荡的幅度(px,基于 1920×1080)
    • 范围:40–200px;约束:SCREEN_CENTER ± DRIFT 须让吉祥物按 MASCOT_SIZE 完整留在屏内;参考值 80 / 50
    • 效果:小 = 微妙悬浮;大 = 大幅追逐、把框推到画面边缘
  • SIZE_BASE — 边界框的平均宽高(px)
    • 范围:200–500px;约束:在所有置信度尺寸下都必须清晰包住目标字形;参考值 320
    • 效果:小 = "标本标签";大 = "框本身就是主体"
  • SIZE_VAR — 逐帧尺寸抖动的半幅值(px)
    • 范围:SIZE_BASE 的 5–10%;约束:< 0.15 × SIZE_BASE,否则会破坏 L 角标视觉;参考值 30(约 320 的 9%)
    • 效果:低端 = 稳定自信的检测器;高端 = 抖动的/正在重拟合的检测器;过大读作"坏了"、为 0 读作"静态 UI"
  • SIZE_FREQ_MULT — 尺寸振荡相对跟踪相位的倍率
    • 范围:1.5–3;约束:避免整数倍率——非整数才读作"持续重算",整数(如 1)会让尺寸与漂移同拍、读作机械;参考值 2.3
  • MASCOT_SIZE — 吉祥物元素实际渲染宽度(px),用于把其中心对齐到 (mx, my)
    • 范围:与 CSS 中 .bg-mascotfont-size 一致;约束:必须与真实渲染尺寸一致,否则吉祥物会跑出框;参考值 240(对应 font-size: 240px

置信度标签参数

  • CONFIDENCE_MEAN — 标签显示的中心百分比
    • 范围:95–99;约束:CONFIDENCE_MEAN + CONFIDENCE_VAR ≤ 99;参考值 97
    • 效果:< 95 读作"不确定",100 读作"假精确",97 是"自信 AI"的甜蜜点
  • CONFIDENCE_VAR — 中心值附近的闪烁半区间
    • 范围:1–3;约束:CONFIDENCE_MEAN ± CONFIDENCE_VAR ⊂ [95, 99];参考值 2
    • 效果:0 = 静止(像截图);> 3 = 不稳定(像坏了)
  • CONFIDENCE_FREQ_MULT — 标签闪烁相对跟踪相位的倍率
    • 范围:3–6;约束:必须高于 SIZE_FREQ_MULT,使标签闪烁比框"呼吸"更快;参考值 4
    • 效果:低 = 与漂移同步(机械);高 = 急促神经质闪烁(读作"实时推理")

合成级常量

  • COMP_WIDTH / COMP_HEIGHT — 合成的像素尺寸(用于推导 SCREEN_CENTER)
    • 范围:由 HF 合成的 data-width/data-height 决定;这不是创作选项,必须匹配父合成;SCREEN_CENTER = (COMP_WIDTH/2, COMP_HEIGHT/2);参考值 1920×1080

配色与字体令牌

  • {detectionYellow} — 角标 + 标签底色。这是一个离散约定而非可调范围:整个行业(自动驾驶 HUD、安防 CV、ML demo)的 AI 检测覆盖层在深色背景上都是黄色;红读作"警告"、绿读作"成功"、蓝读作"信息",都不读作"检测"。推荐饱和暖黄(#facc15 / #FCD34D 一族),参考值 #facc15(Tailwind yellow-400
  • {bgInner} / {bgOuter} — 径向渐变背景的两个端点,应暗且低饱和,让黄色标记弹出;约束:与 {detectionYellow} 保持足够对比;参考值 #161a3a(内)→ #0b0d1f(外)
  • {labelTextColor} — 黄色标签内文字色;约束:与黄色标签底形成对比,通常用同 {bgOuter} 的近黑色;参考值 #0b0d1f
  • {font} / {monoFont} — 场景正文 / 标签字体:{font} 用无衬线体(参考值 "Inter", sans-serif);{monoFont} 用等宽字体(参考值 "JetBrains Mono", monospace)——等宽强化"机器读数"的暗示

七、进阶变体:多目标、丢失重捕获、锁定后推近

规则文档给出三个可直接扩展的变体:

多目标检测(Multi-object detection)

多个框各处于不同相位,各自跟踪各自的吉祥物。每个框维护自己的 onUpdate 驱动集合,并把彼此的初始相位错开 Math.PI / N,避免所有框同步"滴答"造成机械感。

丢失再捕获(Lost-then-reacquired)

框先淡出到 LOST_OPACITY(约 0.2–0.4)并持续 LOST_DUR,随后弹跳到新位置重新锁定,并闪出 "REACQUIRED" 标签:

tl.to(box, { opacity: LOST_OPACITY, duration: LOST_DUR }, LOST_START);
tl.to(
  box,
  { opacity: 1.0, duration: REACQUIRE_DUR, ease: `back.out(${REACQUIRE_BOUNCE})` },
  REACQUIRE_START,
);
tl.to(label, { textContent: "REACQUIRED · 99%", duration: 0 }, REACQUIRE_START);

注意 REACQUIRE_BOUNCE 取约 1.8–2.5,让"重新锁定"比初始入场更干脆有力;而 textContent 因为写死在时间轴位置 0 时长,天然是 seek-safe 的离散状态切换(与 hyperframes-animation 中"按时间阈值切换文本状态"的手法同源)。

跟踪后推近(Tracking-then-zoom)

跟踪结束后,相机(通过 viewport-change.md 规则)向被跟踪的框推进。组合语义:"AI 发现了什么,现在放大给你看。" 配合 viewport-change 的 focus-lock 变体,可以让相机持续锁定正在移动的目标框。

八、关键原则与红线约束

Key Principles(创作层面)

  • 黄色 + 深色背景是检测约定:换任何色相都会丢失体裁信号;
  • 框永远包含目标:必须每帧都从目标位置重算框位置,绝不能滞后跟随——框一旦延迟,读作"坏掉的跟踪器"而非"聪明的 AI";
  • 约 5–10% 的微妙尺寸变化:太大像检测器迷惑,恰到好处才读作"实时重算";
  • 用角标而非整框:L 型角标是体裁签名,整圈边框只是普通 UI 框;
  • 置信度标签只在紧窄区间闪动(中心值 ± 波动在 [95, 99] 内):区间外读作"不确定",≥100 读作"假精确";
  • 跟踪运动不用 CSS 动画,必须走时间轴 onUpdate:HyperFrames 逐帧 seek 与 CSS 动画不同步。

Critical Constraints(工程红线)

  • 时间轴必须 paused:gsap.timeline({ paused: true })
  • 注册键 = data-composition-id(与上文 data-attributes 契约闭环)
  • .track-box / .corner禁止 CSS 动画——必须时间轴驱动
  • .track-box 声明 will-change: transform, width, height
  • .track-box 声明 pointer-events: none(纯装饰覆盖层)
  • 框位置每帧从目标位置重算——绝不让框位置与目标分开各自补间

九、规则组合与配套技能

ai-tracking-box 很少单独出场,规则文档明确给出与同目录规则的组合方式,这些链接在原文档中均为相对于该文件自身的局部路径,以下统一转换为仓库根目录下的完整相对路径:

hyperframes-animation 技能内的路由方式:先用 rules-index.md 按 tag 挑选原子规则,再按需加载 blueprints-index.md 的整场景模板;创作完成后可用 scripts/animation-map.mjs 审计时间轴的死区与生命周期。

规则文档同时声明它应与以下 HF 技能配对使用:

  • hyperframes-animationSKILL.md)— onUpdate 驱动多元素位置的全部动效知识
  • hyperframes-coreSKILL.md,及其 data-attributes.mddeterminism-rules.md 参考)— 合成接线与确定性渲染契约
  • hyperframes-cliSKILL.md)— hyperframes lint / validate / inspect / preview / render 全流程工具链

十、小结:把"伪 AI 检测"做成真事实感的三条心法

回顾整条规则,从 OpenMontage 这套 700+ 技能文件的设计里可以提炼出三句最可迁移的经验:

  1. 体裁正确性先于技术正确性:黄色 #facc15、L 角标、等宽置信度字体、95–99% 的紧窄读数区间——这四件套缺一件,"AI 检测"的直觉都会崩塌,而这与技术实现无关,属于领域视觉语言;
  2. 确定性框架下用"相位代理 + onUpdate"实现"看起来随机实则确定":所有抖动、漂移、闪烁都由一个线性推进的相位参数派生,因此画面既生动又能被逐帧精确复现,这是 HyperFrames 能离屏渲染的根基;
  3. 把"不可靠"做成设计参数而非缺陷:边框会呼吸、置信度会跳动、偶尔丢失再捕获——这些"算法瑕疵"恰恰是实时检测的拟真来源,规则文档把每一项都量化为可调范围与约束,让作者能精确控制"多真实才算真实"。

若需要把该场景接入完整作品,可从 README.md 了解 OpenMontage 的整体管线,并在 .agents/skills/hyperframes-animation/rules/ai-tracking-box.md 基础上直接复制 HTML/CSS/JS 三件套做变量替换与参数微调。

登录后查看全文
热门项目推荐
相关项目推荐