首页
/ HyperFrames oversized-cursor 技法详解:让"超大 macOS 指针"成为发布会视频的视线载体与因果点火器

HyperFrames oversized-cursor 技法详解:让"超大 macOS 指针"成为发布会视频的视线载体与因果点火器

2026-09-05 14:59:36作者:卓炯娓

HyperFrames 仓库的 .agents/skills/ 下维护了一套面向 Agent 的"项目本地 skill",其中 oversized-cursor 定义了发布会(launch video)片中的"超大 macOS 指针"家庭风格(house style):它从屏幕外物理入场、沿单一矢量把观众视线带到下一个兴趣点、用一次可感知的"点击"点燃下一个动画节拍,再物理离场。读完本篇,你将掌握这套指针的尺寸与外观约定、入场/离场法则、尖端定位(tip-targeting)与点击按压参数、点击点火(click-ignition)的节拍编排,以及它在仓库中对应的可挂载注册组件(含变量、时间包络与同步点),并能直接在 HyperFrames 合成里复刻这套指针运镜。

为什么需要"大指针":最便宜的动效来源之一

文档开宗明义:大指针运动是发布会视频中最便宜的高收益动效来源之一——一个元素、纯 transform 补间,就能同时完成三件事(见 SKILL.md):

  1. 带视线:在否则会显得"死掉"(dead)的静止场景里,把观众眼睛带过整块画面;
  2. 给因果:为 morph/转场提供因果点火——"是这次点击导致了那个变化";
  3. 断旧态:在新场景或复杂动画序列启动时,把视线从"陈旧状态"里切分出来。

原则是 Bigger is better:真实尺寸的指针在视频尺度下会直接消失。

从仓库结构看,该 skill 的定位很清晰:.agents/skills/README.md 说明 .agents/skills/ 是 Codex CLI 自动发现的项目本地 skill 目录(与可分发的 skills/ 目录刻意分成两个命名空间),而 oversized-cursor 正是 changelog-video(每周 changelog 视频流水线)五个依赖 skill 之一,与 motion-doctrinecut-the-curvecaptions-overlayseam-craft 并列,共同构成周更视频的路由图。指针外观与定位的这套约定同时也是 skills/hyperframes-animation/rules/ 下其他指针规则的基准——例如 cursor-drag.md 明确写着"指针外观、尺寸、屏外入场与尖端定位,全部委派给 oversized-cursor 家庭教义",它自己只负责拖拽机制。

尺寸与外观:家庭约定(House Convention)

  • 全帧场景:7cqw(在 1920 宽下约 134px);在 mock 内的小帧变体用 4.6–5.5cqw绝不再小
  • 全局使用同一条 SVG 箭头几何。两套经过验证的填充:白色主体 + 黑描边,或黑色主体(#1c1c1c)+ 白描边(1.4px)。按场景对比度二选一,同一部片子内保持一致
  • 品牌母题指针(the power play):macOS 箭头是默认值,不是强制项。当被展示品牌有可辨识的指针身份——协作设计工具的彩色多人协作箭头带姓名标签(Figma 式)、创意套件的精密十字准星、有辨识度的产品指针——就换用那个指针:对熟悉产品的人是瞬间可读的品牌语言。所有法则不变(超大尺度、物理入场/离场、尖端定位、点击点火),姓名标签变体作为刚体整体运动(标签拖在箭头后)。仅当母题真正可被识别时才使用——没人认得出的指针只是一支奇怪的箭头,应回退 macOS 默认。

基线 CSS(来自 SKILL 文档,含关键内联注释):

#root .cursor {
  position: absolute;
  left: 48%;
  top: 115%; /* 屏外下方——静止姿态本身就是"在屏幕外" */
  width: 7cqw;
  height: 7cqw;
  z-index: 20;
  filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.3));
  pointer-events: none;
  will-change: transform;
}

四个硬性要求:filter: drop-shadow(0 4px 6px rgba(0,0,0,.3))pointer-events: nonez-index 压过全部场景内容、will-change: transform

仓库中编译自这份 SKILL 的可挂载组件 oversized-cursor.html 把这些约定落成了带注释的硬不变量:.oc-cursor 上以注释标注 INVARIANT: cursor size floor is 7cqw(并加 min-width/min-height: 34px 兜底小宿主盒),两套填充通过 data-variant="light|dark" 切换,描边宽度同样是 1.4(见该文件 L144–L180 的 CSS 区块)。

入场法则:物理入场,绝不"揭示"

指针永远从屏幕外入场(规范方向:自下方 top: 115–120%),并用一次减速滑行(decelerating glide)直达第一个目标——它必须让观众感觉"走进来了"。绝不在静止位置用 opacity 淡入,也绝不用遮罩揭示——那会读起来像一个 glitch,文档将其标记为"真实、反复观察到的失败模式"。

路径规则:

  • 默认路径是沿 y 轴笔直向上到目标——不做碎片化折线;
  • 对角线入场可以接受,前提是它本身就是故事(例如朝一个偏离主轴的目标入场),但无论哪种情况都必须是单一连续矢量

参数:duration: 0.4–0.92sease: power3.outfromTo 上加 immediateRender: false

tl.fromTo(
  cursor,
  { left: "48.6%", top: "115%" },
  { left: "48.6%", top: "55%", duration: 0.85, ease: "power3.out", immediateRender: false },
  0.25,
);

注册组件的实现与之逐条对应:静止位取 xAt(48) / yAt(116)(注释即 "resting pose IS off-screen"),入场滑行固定 0.85s、power3.out,整段 IN 窗口按 IN_BASE = 1.17(0.85s 滑行 + 0.1s 压缩 + 0.22s 回弹)计算(oversized-cursor.html)。

一个值得注意的源码级差异:SKILL 的入门示例补间 left/top 百分比(适合宿主直接写场景),而注册组件刻意改为只补间 transform 的 x/y(px)——组件内注释解释了原因:在逐帧 seek 的捕获引擎下,布局属性会被吸附到整数设备像素,慢速缓动会卡顿,因此读一次舞台尺寸、把百分比换算成 px 后走 transform,这是 HyperFrames producer 逐帧渲染对确定性的要求。手写场景沿用 SKILL 示例即可,编译成可复用组件时应采用 transform-only 写法。

尖端定位与点击按压(Tip-targeting & the Click Tap)

热点是箭头的尖端(tip),不是盒子中心:让尖端落在目标中心,并且所有按压缩放都绕尖端枢转——对 24 单位 viewBox 的家庭箭头路径,枢轴是 transformOrigin: '21% 14%'

点击 = 非对称的压缩/回弹(1:2 时长比读起来才是真实的一次 tap):

tl.to(cursor, { scale: 0.84, duration: 0.1, ease: "power2.in", transformOrigin: "21% 14%" }, t);
tl.to(
  cursor,
  { scale: 1, duration: 0.22, ease: "power2.out", transformOrigin: "21% 14%" },
  t + 0.1,
);

目标端的反应是独立的、并行的补间(按钮:scale: 0.94 + 按压颜色/阴影,与按压同一起点 t 开始)。只点指针本身的 tap(例如聚焦文本输入框)没有目标端反应。目标侧可搭配 cursor-click-ripple / press-release-spring

组件里的对应实现精确到同一个锚点:开场一次性 gsap.set(cursor, { xPercent: -21, yPercent: -14 }) 把盒子的 21%/14% 点(尖端)对齐到后续所有 x/y 补间的落点(oversized-cursor.html);涟漪元素 .oc-ripple 的 CSS 也锚在 left: 21%; top: 14%,与 transformOrigin 枢轴同点;目标反应是 scale: 0.94, power2.in 的并行补间,起于 CLICK_AT(滑行结束时刻),随后跟涟漪扩散与 --oc-ignite 变量驱动的"点燃"变色(L351–L379)。CLICK_AT 被定义为固定偏移(IN 段末尾),永不落在弹性的 HOLD 段里——这个时刻同时是混音阶段的同步点(SYNC POINT),用于挂一次柔和 UI 点击 SFX。

点击"点燃"下一个节拍(The Click IGNITES the Next Beat)

核心戒律:绝不让 morph、打字段落、窗口变形或任何定义场景的动画"自己开始"。把指针停在触发物上,让点击同帧地导致它:

  • click ▸ 菜单/子菜单级联、开关翻转(toggle flip)
  • click ▸ 输入框打字启动
  • click ▸ 编辑器 morph 收缩 / 窗口缩小
  • click ▸ logo 点火 / 飞行发射
  • click ▸ 产品 mock 中播放态翻转 + UI 生命苏醒

在它不拥有的长节拍期间(打字、旁白),指针漂到一边(drift aside,0.5–0.9s,power2.out)——绝不冻结在动作上方,绝不原地晃动。

注册组件把"漂移"量化成了时间函数:漂移延迟取 min(0.22, HOLD × 0.3),漂移时长取 max(0, min(0.7, HOLD − 延迟)),漂移落点是目标点横向 ±16%(越过中线则反向)、纵向 +10%,ease power2.out,且 overwrite: "auto" 保证不残留冲突补间(oversized-cursor.html)。若 HOLD 太短(driftDur ≤ 0.05s)则整段漂移直接省略——"要么漂开,要么干脆不动",与 SKILL 的"never wobbles idly"一致。

离场法则与跨场景交接(Exit Law & Cross-Scene Handoff)

两种被认可的离场——都是物理性的,绝不做原地 opacity 淡出

  1. 离开画面:朝最近的边缘加速离开,power2.inleft:'118%'left:'-12%'top:'116%'),时长 0.5–0.7s。组件默认即向下:tl.to(cursor, { y: yAt(120), ease: "power2.in" }, OUT_AT),OUT 窗口固定 0.6s。
  2. 切线交接(cut-the-curve handoff):在硬切前最后约 0.3s,指针开始朝下一场景的第一个点击点加速(power2.in),覆盖该路径的前约 1/3;下一合成用 gsap.set 把指针置到交接姿态,再以匹配的速度用 power2.out 续行。指针本身成为缝合接缝的载体元素:
// 场景 A,最后 0.3s —— 启程:
tl.to(cursor, { left: "40.7%", top: "63.7%", duration: 0.3, ease: "power2.in" }, CUT - 0.3);
// 场景 B,t=0 —— 以匹配速度完成:
gsap.set(cursorB, { left: "40.7%", top: "63.7%" });
tl.to(cursorB, { left: "22%", top: "45%", duration: 0.6, ease: "power2.out" }, 0);

这与仓库姊妹 skill cut-the-curve 的核心原则同源——"在峰值速度处切,且切点两侧方向与速度匹配"。该 skill 用镜像的 power4.in / power4.out 让两个半程拼成一条完整 power4.inOut,从而保证接缝处速度精确相等;指针的 cut-the-curve handoff 用 power2.inpower2.out 达到同样目的:交接点两侧的速度向量连续,硬切被"速度"而不是"透明度"隐藏。

编译产物:可挂载的注册组件

上述 SKILL 约定在仓库中有一个编译成品的挂载式子合成(sub-composition):registry/components/oversized-cursor/ 下的组件文件通过 data-composition-src 由宿主 clip 加载(运行时只克隆 <template> 内容,<head> 在挂载时被丢弃)。默认时间 4.2s,时间包络为:

时间 性质 内容
IN 0.00s – 1.17s 固定 屏外入场滑行(0.85s)+ 点击按压(0.32s)
HOLD 1.17s – D−0.60s 弹性 点击点火播放、指针漂离、随后驻留
OUT D−0.60s – D 固定 指针加速离场;exit: fade|up 时整个舞台(含目标)一并离场

变量声明(registry-item.json):

id 类型 默认 说明
cursor_variant enum light light(白主体)/ dark(近黑主体),按场景对比度选
target_x number (%) 55 尖端落点,宿主盒百分比(15–85)
target_y number (%) 55 尖端落点,宿主盒百分比(15–85)
click_label string Generate 被点击目标上的标签
exit enum none none 保留点燃后的目标至切点;fade/up 让整段舞台随 OUT 离场

宿主挂载示例(来自组件 README):

<div
  class="clip"
  data-composition-id="oversized-cursor"
  data-composition-src="./oversized-cursor.html"
  data-variable-values='{"target_x":62,"target_y":48,"click_label":"Render"}'
  data-start="0"
  data-duration="4.2"
  data-track-index="0"
></div>

弹性根:不声明 data-width/data-height,填充宿主 clip 给的任意盒;时间线注册在字面量 oversized-cursor 键下。组件还内置了时长保护:当 data-composition-duration 短于 IN_BASE + OUT_BASE(1.77s)时,IN/OUT 按比例收缩、HOLD 归零,保证入场与离场两个"机制性"片段永远完整播放。

实施检查清单

落片前逐条核对(源自 SKILL 文档 Checklist,并叠加组件 README 的三条不变量):

  • [ ] 全帧 ≥ 7cqw(mock 内 4.6–5.5cqw)——拿不准就加大
  • [ ] 从屏幕外沿单一连续矢量入场(无 fade / mask reveal)
  • [ ] 尖端落在目标中心;按压绕 transformOrigin: '21% 14%' 枢转
  • [ ] 每一次点击都同帧地导致某件事
  • [ ] 非自有节拍期间漂到一边;零原地晃动
  • [ ] 物理离场(出画面或 cut-the-curve 交接)——无原地淡出
  • [ ] (组件化时)尺寸下限 7cqw;运动只用 transform,永不补间 left/top;涟漪与点击枢轴都锚在箭头尖端 (21%, 14%)

小结

oversized-cursor 在 HyperFrames 中不是一个"组件",而是一套可被 Agent 直接执行的指针导演教义:尺寸下限、物理入/离场、尖端定位、点击点火、漂离驻留——六条法则全部带有具体数值(7cqw0.85s power3.out0.84 / 0.1s / 0.22s 的按压、21% 14% 枢轴、power2.in 离场)。仓库里 SKILL.md 是教义本体,注册组件 是把教义编译成可挂载、可变量化、逐帧确定的时间线,两者一一对应;再配上 cut-the-curve 的速度匹配接缝与 cursor-drag 等指针动词规则,就构成了 HyperFrames 发布会流水线里完整的"指针层"。

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

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384