Oil Motion运行时控制器源码剖析:frame-scrub与分段播放的阻尼、环形距离和反向撤回
Oil Motion运行时控制器源码剖析frame-scrub与分段播放的阻尼、环形距离和反向撤回【免费下载链接】oil-motion设计并实现随滚动、拖动、指针或状态变化响应的网页动画覆盖素材、时间轴和运行时。项目地址: https://gitcode.com/gh_mirrors/oi/oil-motionOil Motion 是一个把 AI 视频、序列帧变成网页交互动画的开源 Skill它负责生成关键帧、编译时间轴并通过运行时控制器让画面跟随滚动、指针、拖动或状态变化。本文剖析它运行时层的核心源码 assets/interactive-motion.tsframe-scrub 控制器如何用阻尼让画面平滑随动、如何用最短环形距离处理 360° 旋转输入以及 segment-playback 控制器如何实现分段播放与反向撤回。先搞清楚控制器是怎么选出来的Oil Motion 规定“格式选择”和“播放方式”是两件独立的事。预算脚本 scripts/motion_budget.py 根据 Motion Brief 中的time_control直接决定runtime.controller映射关系只有三种见 references/runtime.mdtime_controlruntime.controller行为scrubframe-scrub输入值持续映射到帧位置停手画面停在原地segment-playsegment-playback输入只选择下一状态片段随后按时间自行播放autonomousautonomous-playback时间自行推进交互只负责开始/暂停所有控制器都只读取编译生成的build/timeline.json页面里不允许维护第二份时间常量。本文重点拆解前两个控制器。frame-scrub输入停在哪画面就停在哪createFrameAnimatorinteractive-motion.ts#L66-L158是 frame-scrub 的完整实现对外只暴露四个方法setTarget(frame)直接指定目标帧setProgress(0~1)把一维进度映射到progress × (frameCount - 1)setDirection(x, y)把指针相对主体的方向角映射到帧环上getCurrentFrame()/destroy()读取当前位置、释放动画帧。阻尼为什么快速甩动指针不会闪烁核心在smoothDamp函数interactive-motion.ts#L36-L64它移植了 Unity 经典的 SmoothDamp 算法用omega 2 / smoothTime把平滑时间换算成角频率smoothTime默认0.11秒——值越小跟随越快值越大“拖尾”越明显用maxSpeed限制每帧最大位移默认frameCount × 2即最快约半秒扫完整个时间轴防止指针急甩时帧数瞬间跳变每帧按指数衰减更新速度和位置并在越过目标点时强制落位归零L56-L62保证不会过冲后回弹。渲染全部集中在requestAnimationFrame循环里L95-L124输入事件只更新target不直接碰 DOM当位置与目标差、速度都小于0.002时主动停表符合项目“每个动画帧最多一次 DOM 写入、状态稳定时停止 rAF”的性能验收标准。若系统开启了prefers-reduced-motion则直接跳到目标帧不做连续 scrub。最短环形距离360° 展台自转的关键当素材是闭环动画circular: true如角色圆周注视、产品展台自转不能把帧号当直线处理。wrap与shortestCircularDeltainteractive-motion.ts#L25-L34负责这件事delta wrap(to) - wrap(from) 若 delta 帧数/2 → delta - 帧数 若 delta -帧数/2 → delta 帧数也就是说从第 239 帧转到第 1 帧240 帧图集走的是2 帧的短路径而不是倒退 238 帧。setTarget在环形模式下会把目标改写成position 最短距离L133-L139阻尼系统看到的就是一条连续前进的轨迹。setDirection(x, y, startAngle)L140-L145则把指针极角归一化到0~1再乘帧数默认起始角-0.75π正好对应“指针在下方时角色正视镜头”。一个 240 帧、16 列 15 行的环形图集配置示例可参考 assets/motion-manifest.example.json。segment-playback分段播放与反向撤回“点击下一章节播放转场”这类交互用的是createSegmentPlayerinteractive-motion.ts#L257-L512。它初始化时就严格校验timeline.jsonstart hold endExclusive、各段不重叠、states数量必须等于段数加一、状态 ID 唯一且与from → to顺序一致——任何一项不满足直接抛错不进入“运行时才崩”的状态。正向播放速度曲线属于时间轴每段可声明播放速率曲线SegmentRateCurveL233-L243constant恒定速率edge-mid-edge两端快、中间慢按cos²权重在 edgeRate 与 midRate 之间插值适合“起势快、结尾快”的镜头感。正向播放直接调用video.play()并用requestVideoFrameCallback逐帧监听进度L322-L331不支持时才回退 rAF文档明确禁止用低频的timeupdate判断停帧。反向撤回不依赖负 playbackRate 的手动倒放这是本文件最有巧思的部分。浏览器普遍不支持负playbackRate所以反向时控制器暂停视频、手动逐帧回退currentTimeL428-L438video.pause() video.currentTime max(targetTime, currentTime - rate × delta)围绕这条倒放链路源码做了三层防护边界间隙清除removeBoundaryGapL349-L376在起播和每帧 tick 时检查当前时间是否落在“上一段 hold 与下一段 start 之间”的剪辑缝隙里若是则直接跳过缝隙避免倒放时画面卡在半透明接缝帧上精确落位接近目标frameDuration/2内就调用settleL378-L386——先pause()再把currentTime精确设到目标状态的hold杜绝“越过目标再回跳”快速连续输入可取消每次startRun递增runTokenL388-L390旧的 tick 回调发现 token 不匹配立即退出cancel()则直接作废当前任务并暂停视频。因此用户连点五次“上一步”只有最后一个目标生效这正是 runtime 规范中“快速连续输入只保留最新目标”的落地。step(-1)/step(1)L485-L487把方向增量转成goTo(targetState ± 1)边界状态自动 clamp不会越界出空状态。分步手势把惯性滚轮合并成一步分段播放与分页导航组合时输入侧由 assets/step-gesture.ts 的createStepGestureAdapter统一处理L44-L67累计增量达到threshold默认 40px才触发一次onStep把一次滚轮/触控板惯性序列合并成一个方向意图而不是每个 wheel 事件跳一个状态反向输入立刻清零累计值并解锁方向天然支持“上滚两格再下滚一格”的撤回idleMilliseconds默认 140ms无新输入后自动复位setProgrammaticNavigation(true)可屏蔽页面自身平滑滚动引起的误触发。手势阈值、惯性结束判定只写在这一处媒体控制器和分页组件不得各写一份。接入与验收要点结合 SKILL.md 第 8 步与 references/runtime.md接入两个控制器时记住这几条硬性要求一个持续存在的媒体实例切换状态不替换src、不重建视频节点分段播放的反向永远是“从当前画面撤回”不得换源硬切时间值只来自编译结果hold、start、endExclusive全部取自最终编码帧禁止手工推算反向必须倒放同一段推进变拉远、溶解变复原爆炸、泼洒这类倒放违反直觉的动作要单独生成反向片段降级路径prefers-reduced-motion使用合同指定的静态状态资源失败时回退静态画面并解锁页面。从smoothDamp的过冲防护、到shortestCircularDelta的环形取短、再到反向撤回的 token 取消机制两个控制器共同体现了 Oil Motion 的一条设计原则输入事件只表达意图平滑、落位和取消都交给共享控制器——这也是它的动画在快速反向、连续输入下不粘滞、不抽动、不回跳的原因。更多运行时细节可查阅 references/runtime.md交付格式的选择逻辑见 references/delivery-selection.md。【免费下载链接】oil-motion设计并实现随滚动、拖动、指针或状态变化响应的网页动画覆盖素材、时间轴和运行时。项目地址: https://gitcode.com/gh_mirrors/oi/oil-motion创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

30 seconds of code:使用 `elementFromPoint()` 精确定位页面任意坐标处的 DOM 元素

30 seconds of code:使用 `elementFromPoint()` 精确定位页面任意坐标处的 DOM 元素

教程文档 【免费下载链接】30-seconds-of-code Coding articles to level up your development skills 项目地址: https://gitcode.com/gh_mirrors/30/30-seconds-of-code 点击查看 免费下载 在浏览器开发中,判断"用户鼠标当前悬停在哪个元素上&qu…

2026/10/4 5:51:04 阅读更多 →
AWS MFA丢失恢复指南:IAM与Root账号全流程实操

AWS MFA丢失恢复指南:IAM与Root账号全流程实操

上个月,运维群里突然炸了:同事的手机在水里泡了一夜,Google Authenticator 里的 AWS 根账号 MFA 也跟着没了。那一整天,我们都在折腾怎么重新拿回控制台权限。类似的场景我遇到不止一次——有人换手机忘了迁移验证器,有…

2026/10/4 5:51:04 阅读更多 →
零基础玩转华为云CodeArts代码智能体实战指南

零基础玩转华为云CodeArts代码智能体实战指南

1. 为什么“零基础玩转华为云码道代码智能体”不是一句空话我第一次打开华为云CodeArts界面时,手停在鼠标上三秒没敢点——不是因为界面复杂,而是因为太干净了。没有弹窗、没有强制引导、没有“新手任务”浮层,只有一片灰白底色加几行导航文字…

2026/10/4 5:50:03 阅读更多 →

最新新闻

滑动t检验原理详解与Matlab实现:时序突变点检测实战指南

滑动t检验原理详解与Matlab实现:时序突变点检测实战指南

先说清楚这东西是干什么的。滑动t检验是气象、水文、环境这类时序数据分析里非常常用的突变检验方法,核心思路很简单:把一段序列按时间顺序开两个窗口,比较这两个窗口的均值差异是否显著,如果某个时刻前后两段数据的均值出现了远超…

2026/10/4 6:18:21 阅读更多 →
从认知镜像到真理探寻器——贾子认知免疫理论视域下生成式人工智能的底层缺陷、权重秩序与治理重建

从认知镜像到真理探寻器——贾子认知免疫理论视域下生成式人工智能的底层缺陷、权重秩序与治理重建

从认知镜像到真理探寻器 ——贾子认知免疫理论视域下生成式人工智能的底层缺陷、权重秩序与治理重建 摘要 当前生成式人工智能被广泛描述为具有“惊人能力”的新型智能系统。然而,代码生成、数学计算、长文本写作、多模态处理和工具调用等表层能力,不…

2026/10/4 6:18:21 阅读更多 →
分治算法实战:最邻近点对问题的O(n log n)解法与优化

分治算法实战:最邻近点对问题的O(n log n)解法与优化

1. 为什么这个问题值得专门写一篇:从暴力法到分治法的效率鸿沟最邻近点对问题(Closest-Pair Problem)大概是计算几何领域里最“看着简单、做起来却不那么简单”的问题之一。给你平面上散落的 n 个点,找出距离最近的那两个点。你先…

2026/10/4 6:18:21 阅读更多 →
入门数据结构:一维数组

入门数据结构:一维数组

概述 本文以C语言作为示例语言,手把手教导小白数组的特性与应用 核心概念 数组:一块连续的内存,用来存放多个相同类型的数据。 下标:也叫索引,就是用来表示“数组中第几个元素”的编号。通常写在[]中来表示数组中第一个…

2026/10/4 6:18:20 阅读更多 →
AI生成内容交付前的五道审核关卡与纠错流程

AI生成内容交付前的五道审核关卡与纠错流程

1. 为什么“AI生成直接发”是个危险动作1.1 客户交付场景下,AI内容的风险到底在哪先说一个我亲身踩过的坑。去年帮一个做企业培训的客户赶一批课程文案,二十多篇稿子,我用大模型批量生成后只做了简单通读就打包发了过去。结果第三天客户那边反…

2026/10/4 6:18:20 阅读更多 →
AI Agent时代:计算、推理与数据必须重新整合的云架构

AI Agent时代:计算、推理与数据必须重新整合的云架构

1. AI Agent 时代,云为什么必须“重新整合”1.1 从一个真实场景说起:Agent 把云的短板全暴露了去年下半年我帮一个团队调一套客服 Agent,模型用的是开源 70B 量化版,部署在云主机上。单轮对话测试时延 800ms,看着还行。…

2026/10/4 6:17:20 阅读更多 →

日新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:35 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →