新闻详情

新闻详情

首页 / 资讯中心 / 详情

videojs v10 源代码系列解读: 25 · 输入动作注册表:手势/热键→媒体的桥

发布时间:2026/9/27 6:56:09来源:尧图网络
videojs v10 源代码系列解读: 25 · 输入动作注册表:手势/热键→媒体的桥
播放器有两套输入系统——手势触摸和热键键盘。它们识别的「动作」最终都要落到媒体操作上双击快进 10 秒、按上箭头调音量。v10 在两者之间放了一个共享内核——media-actions.ts的动作注册表。这个设计解耦得很干净而且里面那个「速度循环导航」的实现让我眼前一亮。问题两套输入一套动作想象没有这个注册表的世界手势系统识别「双击右侧」后自己写media.currentTime 10热键系统识别→键后也自己写一遍。两处实现两处维护还都绕过了 store音量 UI 不会更新。v10 的做法把「需要读当前媒体值再计算」的相对动作集中到一个注册表手势和热键都调它「直接调 store 方法」的 toggle 动作由各输入域自己处理。注册表的结构core/src/dom/media-actions.ts47 行// L5 — 四个动作名exporttypeMediaInputActionNameseekStep|volumeStep|speedUp|speedDown;// L7-10 — 动作上下文exportinterfaceMediaInputActionContext{store:AnyPlayerStore;value?:number;}// L14-46 — 名字到 resolver 的扁平注册表exportconstMEDIA_INPUT_ACTION_OVERRIDES:RecordMediaInputActionName,MediaInputActionResolver{seekStep:...,volumeStep:...,speedUp:...,speedDown:...,};扁平的Record名字, resolver没有嵌套配置。每个 resolver 收{ store, value }——只拿 store不碰 DOM/media 元素。四个 resolver 的实现seekStepL15-20相对跳转seekStep({store,value}){if(valueundefined)return;// L16consttimeselectTime(store.state);// L17 — 走 selectorif(!time)return;// L18 — 未配置 time featuretime.seek(time.currentTimevalue);// L19 — 相对 seek}注意 L17——走selectTimeselector不直接摸 media。这带来两个免费好处time feature 没配置时安全降级L18seek 用的是 21 篇讲的那个带supersede抢占 乐观更新的seek()。volumeStepL22-27同理走selectVolumespeedUp / speedDownL29-45循环列表导航这对最有意思。不是「固定步长加减」而是在播放速率列表里循环移动speedUp({store}){constrateselectPlaybackRate(store.state);// L30-32constidxrate.playbackRates.indexOf(rate.playbackRate);// L33 — 当前位置// L34 — 越界即回绕到 0constnextidx0||idxrate.playbackRates.length-1?0:idx1;rate.setPlaybackRate(rate.playbackRates[next]!);// L35}// speedDown 对称idx 0 ? length - 1 : idx - 1 L43为什么循环而不是步长因为播放速率不是连续值——是[0.5, 1, 1.5, 2]这样的离散列表由 playbackRate feature 的playbackRates提供。「0.5」在列表是[1, 2]时会算出 1.5不存在的档位而列表导航永远落在合法档位上。从 2x 再加速回绕到 0.5x——这比「到顶就卡住」的体验好。这四个 resolver 都体现同一个模式通过 selector 从 store 读当前值计算后调 store 的动作方法。全链路在 store 内闭环UI 自动同步。gesture 和 hotkey 怎么消费gesture 侧gesture/actions.ts47 行// L26-34 — 把四个 resolver spread 进手势自己的注册表constGESTURE_ACTION_OVERRIDES{seekStep:MEDIA_INPUT_ACTION_OVERRIDES.seekStep,// L27volumeStep:MEDIA_INPUT_ACTION_OVERRIDES.volumeStep,speedUp:...,speedDown:...,};// L36-46 — 解析函数exportfunctionresolveGestureAction(name){constoverrideGESTURE_ACTION_OVERRIDES[name];// L37 — 先查 overrideif(override)returnoverride;// L38// L41-44 — 通用回退直接调 store.state[name]()// __DEV__ 下未知动作 warnL44}手势动作上下文比 Media 版多event: PointerEventL20——识别器需要原始事件。通用回退L41-44是关键设计查不到 override 的动作togglePaused/toggleMuted/toggleFullscreen这些toggle 类直接store.state[name]()——因为它们本身就是 state 里的方法19 篇不需要读值再计算。hotkey 侧hotkey/actions.ts100 行HOTKEY_ACTIONS是完整 RecordL38-89四个 override 复用同一条目L65/67/69/71。其余 toggle 动作内联实现togglePausedL39-43、toggleMutedL45-47、toggleFullscreenL49-53、toggleSubtitlesL55-57、togglePictureInPictureL59-63。热键独有一个动作——seekToPercentL73-88// 简化constpercentvalue??(key0key9?Number(key)*10:undefined);// L79-82time.seek((percent/100)*time.duration);// L87数字键 0-9 直接跳到 0%-90% 位置——YouTube 风格的键盘交互。value优先显式配置否则从按键推导。设计意图总结把这套结构画出来手势识别器 ──┐ ┌─ seekStep/volumeStep/speedUp/speedDown ├─ resolveXxxAction ┤ MEDIA_INPUT_ACTION_OVERRIDES走 selector 读值计算 热键解析器 ──┘ └─ togglePaused/toggleMuted/... 通用回退直接调 store.state.xxx() │ ▼ store 状态更新 → UI 自动同步分工规则一句话「需要读当前值再计算」的相对动作进共享注册表「直接调用」的 toggle 动作各输入域自己处理或走通用回退。这个设计带来三个收益单一实现——seekStep 的逻辑走 selector、带抢占只写一遍手势热键共用。不绕过 store——所有动作经过 selector/state 方法UI 自动同步不存在「手势改了音量但 UI 没更新」的 bug 类别。扩展对称——加新输入方式比如游戏手柄只需要新的 resolver 包装动作内核复用。小结MEDIA_INPUT_ACTION_OVERRIDES是手势/热键的共享内核四个相对动作。resolver 只拿 store 不碰 DOM——走 selector 读值、调 state 方法。speedUp/speedDown 是循环列表导航——速率是离散档位越界回绕比卡住体验好。toggle 类走通用回退——store.state[name]()直接调。热键独有seekToPercent——数字键跳百分比位置。手势和热键的识别器本身recognizer/coordinator/解析器在卷八52、53 篇详细讲。下一篇先看 presentation 子系统——全屏/PiP/远程播放/方向锁浏览器兼容的重灾区。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

用AgentENV训练Terminal-Bench-2:搭建Agent强化学习的沙箱后端 2026/9/27 6:56:01

用AgentENV训练Terminal-Bench-2:搭建Agent强化学习的沙箱后端

用AgentENV训练Terminal-Bench-2:搭建Agent强化学习的沙箱后端 【免费下载链接】AgentENV AgentENV (AENV) is a distributed platform for running agent environments at scale. 项目地址: https://gitcode.com/gh_mirrors/age/AgentENV AgentENV&#xff…

阅读更多 →
别被建站报价忽悠 揭秘免费做调查问卷的网站真底细 2026/9/27 6:55:54

别被建站报价忽悠 揭秘免费做调查问卷的网站真底细

别被建站报价忽悠 揭秘免费做调查问卷的网站真底细 找建站公司怕被坑高价,这是很多老板心里的痛点。市面上那些号称“全网最低”的建站报价单,往往藏着无数的隐形消费。今天咱们不聊虚的,直接拆解一个看似与建站无关,实则能帮你省下一大笔营销成本的场景…

阅读更多 →
文献阅读 260926-The Origins and Control of Forest Fires in the Tropics 2026/9/27 6:55:35

文献阅读 260926-The Origins and Control of Forest Fires in the Tropics

The Origins and Control of Forest Fires in the Tropics 📌 基本信息 🛠️ 一、 引言部分简要总结 (Introduction Summary) 🔬 二、 研究方法详细介绍与分析 (Methodology Framework) 图片名:Figure 1 图例说明:Figu…

阅读更多 →
mykernel 实验指导(操作系统是如何工作的) 2026/9/27 6:55:35

mykernel 实验指导(操作系统是如何工作的)

姓名: 李令琪 原创作品转载请注明出处 课程:《Linux 内核分析》MOOC 课程地址: http://mooc.study.163.com/course/USTC-1000029000 1. 实验环境与步骤 实验使用实验楼提供的 Linux 虚拟机,内核源码版本为 Linux 3.9.4。首先进入…

阅读更多 →
Jetpack - Hilt 2026/9/27 6:55:22

Jetpack - Hilt

官方文章 参考文章 一、概念 依赖管理不仅可以很好地解决对象繁琐的初始化逻辑,还可以很好的实施控制反转的编码思想。 类中使用的某个对象不是在这个类中实例化的(如汽车类内部创建轮子对象),而是通过外部注入(在外…

阅读更多 →
Manim 中文显示问题报错解决办法 2026/9/27 6:55:22

Manim 中文显示问题报错解决办法

使用Manim直接制作这种动画视频的话是不支持中文的,需要进行一些修改,效果如图所示。 但是修改的方案都太坑,经过自己不断的研究找到了一个比较简单实用的方法。 文章目录 源文件修改 代码修改 源文件修改 实用everuthing找到ctex_template.tex文件。 我这里的路径是D:\M…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉