资讯动态

HyperFrames GSAP 缓动、错峰与函数式动画值:从运动语言到可寻址弹簧物理

发布时间:2026/9/11 21:13:29 来源:尧图企业网站定制
HyperFrames GSAP 缓动、错峰与函数式动画值从运动语言到可寻址弹簧物理【免费下载链接】hyperframesWrite HTML. Render video. Built for agents.项目地址: https://gitcode.com/GitHub_Trending/hy/hyperframes导读HyperFrames 是一个写 HTML、渲染视频的 seek 驱动seek-driven确定性渲染运行时GSAP 是其中 95% 动效工作的默认动画运行时。本文基于 skills/hyperframes-animation/adapters/gsap-easing-and-stagger.md 展开系统讲解 HyperFrames 中的 GSAP 缓动easing体系、错峰stagger编排、函数式动画值function-based values以及gsap.matchMedia的预览用法并深入剖析烘焙弹簧缓动springEase的闭环解析解与可寻址seek-safe原理。读完后你将掌握如何在单条暂停时间轴上为入场、退场、连续运动挑选正确的缓动语气如何用错峰对象把一组元素编排成一个整体节拍以及如何用无状态的弹簧解析解替代有状态的弹簧积分器让动画在逐帧 seek 下保持严格确定。一、先理解 HyperFrames 的运动契约缓动与错峰为什么如此重要在进入 GSAP 具体 API 之前需要先锚定 HyperFrames 的两个核心事实渲染是 seek 驱动的。每支合成composition只有一条paused: true的时间线注册到window.__timelines[composition-id]由框架调用seek()驱动播放头渲染关键动效绝不能调用.play()。因此任何缓动都必须是时间的纯函数——同一时间值每次 seek 都必须产生完全相同的状态。确定性是硬约束。合成中禁止Math.random()、Date.now()、performance.now()、事件驱动动画以及repeat: -1。这条约束直接决定了下文为什么不能使用有状态弹簧库的答案。GSAP 适配器的底层实现在 packages/core/src/runtime/adapters/gsap.tscreateGsapAdapter的seek方法先对时间线执行pause()再通过totalTime或seek把播放头定位到精确时间值得注意的是它先以safeTime 0.001做一次微扰再 seek 到目标时间以强制 GSAP 3.x 在_tTime相同脏状态缺失时也能重新渲染。这套机制要求时间线上的每一个 tween 都是无状态的、可由时间唯一决定的状态函数——这正是本文件所有规则的设计前提。完整的时间线契约见 skills/hyperframes-animation/adapters/gsap-timeline-and-labels.md 与 skills/hyperframes-animation/SKILL.md 中的 Critical Constraints。二、内置缓动家庭、变体与平滑优于弹跳的运动准则2.1 缓动家庭与.in/.out/.inOut变体GSAP 内置缓动家族包括power1、power2、power3、power4、back、bounce、circ、elastic、expo、sine、none。每个家族都有.in、.out、.inOut三种变体。选择口诀入场用.out退场用.in对称移动与连续运动用.inOut。2.2 常用缓动速查表Ease适用场景power1.out、power2.out次要元素的温和运动字幕淡入、小幅位移。不是入场默认值power3.outhouse default、power4.out标准的长尾沉降。入场、标题卡、主角揭示sine.inOut长、慢、平静的运动。交叉淡化、环境漂移back.out(1.7)过冲后沉降。罕见——仅限显式俏皮语域永不作默认elastic.out(1, 0.3)弹簧弹跳。同样仅限俏皮更推荐烘焙弹簧见 Spring Eases 一节expo.inOut干脆、戏剧化。主角场景之间的快速转场none线性带时间对位timed counterpoint的运镜、机械感运动运动准则Smooth beats bouncy平滑优于弹跳。见 rules/spring-pop-entrance.md入场默认power3.out或烘焙的临界阻尼弹簧back/elastic/bounce这类过冲缓动是罕见、显式俏皮的语域不是 house style。bouncy 是 agent 生成视频的头号劝退点。2.3 缓动词汇表性格与情绪缓动是语气tone of voice一支视频如果全程只有一个语气会很无聊在低语—正常—重拳之间变化才有感染力。一份合成应在各节拍上取约3 种缓动性格但变化要在平滑家族内部按能量分层sine/power1平静 →power3标准 →power4/expo重拳不要为求变化而动用过冲。过冲是语域register不是调味料到处用同一个缓动读起来扁平到处用弹跳读起来廉价——后者是更严重的失败。完整调色板每个家族均有.in/.out/.inOut变体家族性格典型用途power1–power4从温和1到激进4的加速曲线通用。power3 是 house workhorsepower2 用于次要温和运动power4 用于戏剧性急停back(N)过冲后沉降。N 控制越过目标多远1轻微4狂野罕见——仅显式俏皮语域。保持 N ≤ 2更推荐 ζ 0.6–0.7 的烘焙弹簧物理沉降elastic(amp, freq)弹簧弹跳。amp幅度freq振荡速度罕见——同上烘焙弹簧是其物理版本bounce球落地式弹跳罕见——仅限物理喜剧语域东西真的在掉落expo极陡加速度曲线远陡于 power4高级/奢华揭示、戏剧化入场sine平滑、有机、无硬边环境浮动、呼吸、Ken Burns、任何循环运动。.inOut用于往复运动circ圆形加速度起始极快、结束极缓反之亦然运镜、场景转场、轨道运动steps(N)N 步离散跳变无插值打字效果、光标闪烁、计数器滴答、复古/数码美学情绪映射让缓动性格匹配节拍的情感内容。平滑/有机缓动sine、power1读起来沉思、漂移激进减速power4.out、expo.out读起来干脆、自信弹簧过冲back.out读起来弹跳、物理——但弹跳是语域而非强调工具只在显式俏皮节拍上使用。分镜的情绪描述应当指引选择哪种性格而不是套公式。三、默认值在时间线作用域声明运动语言时间线级默认值是把该合成运动语言集中记录在一处的最佳实践const tl gsap.timeline({ paused: true, defaults: { duration: 0.6, ease: power3.out }, // house settle —— 平滑优于弹跳 });也可以全局设置gsap.defaults({ duration: 0.6, ease: power3.out });推荐在时间线作用域设置 defaults——它把本合成的运动语言文档化在单个位置后续每个子 tween 自动继承duration与ease不必逐行重复。这与 gsap-timeline-and-labels.md 中用 defaults 代替每行重复 ease/duration的准则一致。四、Spring Eases烘焙物理天生可寻址4.1 什么是iOS 手感所谓iOS 手感其实是阻尼弹簧的速度曲线而不是弹跳快速启动后进入漫长的渐近沉降。优秀的系统动画要么临界阻尼、要么接近临界阻尼——几乎不过冲或完全不过冲。power3.out/expo.out只是近似这条曲线当你需要精确的曲线、或为罕见的俏皮语域需要物理感过冲时就把弹簧的闭式解烘焙成函数缓动。4.2 为什么不能用实时弹簧库交互式弹簧是有状态积分器速度逐帧累积无法确定性 seek——要渲染第 N 帧必须把第 0…N−1 帧全部模拟一遍。而下面这个闭式解是关于进度的纯函数无状态、无同步漂移、按构造即 seek-safe。这也是为什么交互类库的弹簧求解器被禁止用于合成。4.3 springEase 完整实现// springEase —— 阻尼弹簧精确位置曲线作为 GSAP ease 使用。 // response ≈ 一次振荡所需秒数入场取 0.3–0.6 // dampingFraction 1.0 临界阻尼——平滑沉降无过冲house default // 0.80–0.85 ≈ iOS 系统语域——约 1–1.5% 过冲可感而不可见 // 0.60–0.70 显式俏皮——约 5–10% 过冲罕见取代 back.out function springEase({ response 0.5, dampingFraction 1 } {}) { const w (2 * Math.PI) / response; // 无阻尼固有角频率 const z dampingFraction; let pos; // x(t): 0 → 1静止启动v0 0 if (z 1) { const wd w * Math.sqrt(1 - z * z); pos (t) 1 - Math.exp(-z * w * t) * (Math.cos(wd * t) ((z * w) / wd) * Math.sin(wd * t)); } else if (z 1) { const wo w * Math.sqrt(z * z - 1); pos (t) 1 - Math.exp(-z * w * t) * (Math.cosh(wo * t) ((z * w) / wo) * Math.sinh(wo * t)); } else { pos (t) 1 - Math.exp(-w * t) * (1 w * t); } // 沉降时间曲线最后一次离开目标 ±0.1% 的时刻。 // 固定步长扫描仅在初始化时运行一次——确定性无 Math.random / Date.now。 const EPS 0.001; const rate z 1 ? z * w : (z - Math.sqrt(z * z - 1)) * w; // 最慢衰减模态 const SCAN 12 / rate; const N 4800; let T SCAN; for (let i N; i 0; i--) { const t (i / N) * SCAN; if (Math.abs(1 - pos(t)) EPS) { T ((i 1) / N) * SCAN; break; } } const xT pos(T); return { duration: T, // 用作 tween 的 duration——沉降时间本身就是物理 ease: (p) pos(p * T) p * (1 - xT), // 归一化使 ease(1) 1 精确成立 }; }实现要点三种阻尼分支欠阻尼z 1用cos/sin振荡项过阻尼z 1用cosh/sinh双曲项临界阻尼z 1用(1 w·t)·e^(−w·t)的经典临界形式。沉降时间扫描以固定步长4800 步扫描曲线最后一次偏离目标超过 ±0.1% 的时刻作为duration。扫描只在初始化时运行一次且不含任何随机源保证确定性。端点归一化返回的 ease 对进度 p 做pos(p * T) p * (1 - xT)确保ease(1) 1精确成立符合 GSAP ease 契约。工程佐证仓库中与弹簧相关的能力不止这一处。packages/core/src/parsers/springEase.ts提供 Studio 的单参数弹簧 tokenspring(bounce)的解析与端点归一化求值evaluateSpringEase其测试 packages/core/src/parsers/springEase.test.ts 明确断言弹簧从 0 出发、可过冲、精确收敛到 1且对相同输入两次求值结果完全相同确定性断言更高 bounce 值产生更多振荡。这与本文 springEase 的纯函数、确定性、物理沉降哲学同源。4.4 使用方式缓动与时长一起取duration 必须一并来自 helper——沉降时间本身就是物理的一部分覆盖 duration 只是给同一曲线重新计时调速应当通过response参数const settle springEase({ response: 0.4 }); // 临界阻尼 → duration ≈ 0.59s tl.fromTo( #hero, { scale: 0, opacity: 0 }, { scale: 1, opacity: 1, duration: settle.duration, ease: settle.ease }, 0.2, );4.5 参数对照表dampingFraction阻尼比 ζdampingFraction过冲语域1.0默认无单调House settle——即power3.out所近似的精确曲线。产品/企业/严肃基调0.80–0.85约 1–1.5%有生气而不弹跳——iOS 系统默认语域。过冲可感而不可见0.60–0.70约 5–10%仅限显式俏皮与back.out同规则——弹簧的二阶沉降读起来物理back读起来卡通 0.55 12%不要用。卡通抖动区response响应时间responsedurationζ1手感0.25–0.350.37–0.51s紧致急停——芯片、小型 UI0.35–0.500.51–0.74s标准入场0.50–0.700.74–1.03s有重量的主角落地——注意检查t ≤ 0.5s可见性规则4.6 工艺要点Craft notesζ1 vspower3.out真实弹簧前置加载更猛四分之一时刻已走约 67%power3.out约 58%且沉降在更长的渐近尾段最大形状差异约 11%。那条长尾就是高级感的来源——当沉降本身即镜头字标落地、最终定版时使用它。ζ1 时过冲曲线只能用在 transform 上——绝不能用于opacity会越过 1或颜色。把 opacity 拆到同一时间线位置的独立power2.outtween 上。准则不变ζ 低于约 0.8 仍是罕见、显式俏皮的例外见 rules/spring-pop-entrance.md。本节的默认值是 ζ1——真实弹簧物理不是弹跳的许可。五、Stagger把一组元素编排成一个节拍5.1 基本用法gsap.fromTo(.item, { y: 24, opacity: 0 }, { y: 0, opacity: 1, duration: 0.5, stagger: 0.08 });5.2 对象形式gsap.fromTo( .item, { y: 24, opacity: 0 }, { y: 0, opacity: 1, stagger: { each: 0.08, // 每个元素之间的延迟 from: center, // start | end | center | edges | random | index amount: 0.6, // 总错峰时长若同时设置覆盖 each grid: auto, // 用于 2D 错峰 axis: x | y, }, }, );字段速览each相邻元素启动间隔秒from错峰起始方向支持start、end、center、edges、random也可直接传索引数值amount整个序列的总错峰时长设置后覆盖each二者互斥时以amount为准grid为二维网格布局启用自动行列感知错峰axis在主轴x/y上限制错峰方向。5.3 实践准则优先用stagger而不是 N 个带手动delay的独立 tween——当目标数量或顺序变化时它依然正确。用fromTo()而非from()让起始状态显式参见 gsap-timeline-and-labels.md 的子合成入场章节。原因子合成每次宿主片段可见时都会被重新 seekgsap.from()在注册时页面加载快照起始状态播放头跳回data-start之前时该快照可能与真实 CSS 状态脱同步fromTo()显式声明两端回 seek 永远产生相同起始状态。分组错峰参照 spring-pop-entrance.md 的经验值STAGGER取min(0.06, 0.5 / ITEM_COUNT)条目数 3–9确保ITEM_COUNT × STAGGER ≤ 约 0.5s让整组在一个节拍内落地超过 9 个条目错峰会消失应改用擦除/扫掠揭示。六、函数式动画值按索引/属性/尺寸计算每个元素的值任何动画属性都可以是函数(index, target, targets) valuegsap.to(.item, { x: (i, target, targets) i * 50, rotation: (i) (i % 2 0 ? 5 : -5), stagger: 0.1, });回调签名i目标索引0 起target当前目标元素targets目标数组全集。适用场景需要按索引、元素属性或测量尺寸计算逐元素值的地方。相比在循环里逐个构建 tween函数式动画值更省成本、更地道。注意与 SKILL.md 的约束结合预计算布局常量绝不要在 tween 时刻从getBoundingClientRect()推导位置——渲染器并行采样会导致脱同步坐标应在合成 setup 阶段计算一次并复用。七、gsap.matchMedia仅用于预览matchMedia只在媒体查询匹配时运行 setup并在不再匹配时自动还原revert。它适用于浏览器预览时的不同视口尺寸以及prefers-reduced-motion处理let mm gsap.matchMedia(); mm.add( { isDesktop: (min-width: 800px), reduceMotion: (prefers-reduced-motion: reduce), }, (context) { const { isDesktop, reduceMotion } context.conditions; gsap.to(.box, { rotation: isDesktop ? 360 : 180, duration: reduceMotion ? 0 : 2, }); }, );重要限制matchMedia不能替代按合成实际data-width/data-height渲染——HyperFrames 在固定视口下渲染媒体查询只对浏览器中的预览体验有意义不能作为响应式布局的渲染手段。八、把这些规则放进一条合规的时间线将本文要点组装成一段符合 HyperFrames 契约的完整示例window.__timelines window.__timelines || {}; const tl gsap.timeline({ paused: true, defaults: { duration: 0.6, ease: power3.out }, // house settle }); // 1. 主角烘焙的临界阻尼弹簧duration 来自 helper const settle springEase({ response: 0.4 }); tl.fromTo( #hero, { scale: 0, opacity: 0 }, { scale: 1, opacity: 1, duration: settle.duration, ease: settle.ease }, 0.2, ); // 2. 标题power3.out 长尾沉降 tl.fromTo(.title, { y: 24, opacity: 0 }, { y: 0, opacity: 1 }, hero0.1); // 3. 卡片组stagger 成一个节拍函数式动画值做交替微旋转 tl.fromTo( .card, { y: 24, opacity: 0, rotation: (i) (i % 2 0 ? 5 : -5) }, { y: 0, opacity: 1, rotation: 0, duration: 0.5, stagger: { each: 0.08, from: center } }, title, ); window.__timelines[main] tl; // 键必须等于合成根的>node skills/hyperframes-animation/scripts/animation-map.mjs composition-dir \ --out composition-dir/.hyperframes/anim-map九、速查与自检清单入场.out退场.in对称/连续运动.inOut。默认缓动power3.out时间线 defaults 中声明一次重拳用power4.out/expo.out平静用sine/power1。过冲缓动back/elastic/bounce是显式俏皮语域不是调味料需要物理感弹跳时用springEase({ dampingFraction: 0.6–0.7 })。弹簧物理ζ1 临界阻尼是 house defaultζ1 时过冲曲线只上 transformopacity 拆独立 tweenduration 必须取自 helper。错峰优先stagger对象each/from/amount/grid/axis组内落地控制在约 0.5s 内。函数式动画值(i, target, targets) value处理逐元素差异比循环建 tween 更便宜。确定性红线无Math.random/Date.now/performance.now无repeat: -1fromTo显式两端paused: true并注册到window.__timelines。matchMedia仅用于浏览器预览渲染永远以data-width/data-height为准。【免费下载链接】hyperframesWrite HTML. Render video. Built for agents.项目地址: https://gitcode.com/GitHub_Trending/hy/hyperframes创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价