iPhone Duo 对 Web 开发意味着什么(以及 Video.js)
What the iPhone Duo means for web development (and Video.js)
苹果在 iPhone Duo 上通过 feature flag 提供了 Device Posture API 和 Viewport Segments API,前者用 navigator.devicePosture 或 @media (device-posture。
2026年10月6日•10分钟阅读
你可能会以为,在Video.js v10.0.0 发布之后,我们的第一篇文章会是关于可组合架构、编译器,或者我们库智能体体验研究的多部分系列深度探讨。
但你知道吗?我们一直在拼命努力让 Video.js 顺利发布。所以,与其写一篇真正的博客文章,我决定把周末花在一个小副业项目上:深入研究我们将在 iPhone Duo 上能够访问的 Web API。
我知道,我知道,这种折叠的东西已经在 Android 上流传多年了。但自从我心爱的 HTC One 十多年前坏掉之后,我一直是 iOS 用户。而现在,Tim John Apple 终于下令,轮到我折叠手机了。
而且我对轮到我很兴奋。不仅是因为再次拥有一部小手机(iPhone mini,我想你 🥺)的喜悦。还因为这对开发者意味着什么。Apple 发布了六个视频,讲述如何为 iPhone Duo 构建出色的应用。这些视频涵盖了告诉你设备物理特性和状态的 API,并且充满了设计灵感,展示了开发者现在可以构建的应用类型和交互方式。
但这是 Apple。他们有没有给我们 Web 开发者留下什么残羹剩饭?
iPhone Duo 有哪些可用的 Web API?
下载 Xcode 27.1 beta1 后,我立刻启动了模拟器设备中心,启动了一台 iPhone Duo,直奔设置,深入研究了功能标志。2

我热爱功能标志。这个列表简直就是 Web 未来的玩具箱;那些也许某天我们能玩到的酷炫功能。我停下来,顺便查了几个。比如,CSS Rhythmic Sizing 到底是什么鬼??
但不行。我得集中注意力。我来这里是为了两件具体的事。滚动了一会儿后,我找到了它们。设备姿态 API 和视口分段 API。
设备姿态 API
设备姿态 API基本上告诉你,你正在看的显示器是 continuous(例如,你的普通屏幕,平的或曲面的,太2018 年了)还是 folded(例如,部分折叠的折叠手机,像笔记本电脑)。这在 JavaScript 中有效——navigator.devicePosture——或在 CSS 中——@media (device-posture: folded)。
视口分段 API
视口分段 API告诉你显示器的各个区域。在 JavaScript 中,window.viewport.segments 会给你一个 DOMRect 数组,告诉你各分段的大小、形状和位置。
在 CSS 中,你可以通过两种方式了解分段。首先,@media (horizontal-viewport-segments: n) 和 @media (vertical-viewport-segments: n) 让你响应(你猜对了)水平和垂直视口分段的数量。其次,你可以使用 CSS 环境变量访问任何分段的位置和大小。想访问右上角分段的宽度?env(viewport-segment-width 1 0) 就能帮你实现。(第一个数字是水平索引,第二个是垂直索引)。
比如说,你有一个全出血的两列布局,当屏幕折叠时,你想让它吸附到各个分段上,这样你的内容就不会进入折痕。你可能会写这样的代码……
这会产生这样的效果


为折叠手机构建 Web 视频播放器
好吧,这些都挺好,但让我告诉你我们真正来这里的原因。在苹果媒体活动之后,我看到一些人试用了新的 Netflix iPhone Duo 应用,折叠播放器非常合理。视频在上半部分,控件在下半部分,还有一个微妙的效果,将视频反射到下半屏幕上。

在 Video.js 中度过了一年,显然我的第一个想法是“我们能做这个吗?”
简短的回答是“不能”。尽管打开的 Duo 基本上就是一台 iPad,苹果仍然不允许我们的元素全屏。我们只能使用原生控件。

但这样结束博客文章太无聊了。而且不知为何,Fullscreen API 确实作为一个功能标志可用。所以我进去启用它……然后……

天哪,那些是 iPhone Duo 上全屏的 Video.js 控件吗??我觉得不需要太多想象力就能猜到接下来会发生什么。
让我们看看我能否用 Video.js 组件和 CSS 重现 Netflix 的 UI。
将控件放在下半屏幕
我首先获取一个带有 shadcn CLI 的 Video.js 皮肤,并为其添加一个全新的部分。3
我还需要一些额外的控件和图标来匹配 Netflix 的 UI,所以我添加了一点更多的 JS:
从这里开始?如果你一直在关注,这个 CSS 应该不会太令人惊讶。我们检查是否处于垂直折叠姿态,然后定位视频和控件。4
瞧!如果你忽略苹果在顶部绘制的自定义全屏控件,你几乎可以假装这是一个原生应用。

在下半屏幕反射视频
既然我们在这里,让我们更进一步。Netflix 视频“反射”到下半屏幕。我们也能做到吗?
首先,我尝试-webkit-box-reflect,它很乐意反射普通 DOM 元素,但不幸的是不能反射<video>。至少在 iOS Safari 上不行。然后,我记得我的一位同事构建了一个Mux Player 版本,模仿了YouTube 的环境模式。
这是它的要点。首先,我们将每一帧复制到一个小画布上:
然后,我们翻转那个画布,模糊它,并淡化它:
就是这样。控件后面有一个柔和的投射。

就在那个重磅消息上……
大约现在,我想起我必须启用三个功能标志才能到达这里。虽然我可以想象苹果启用 Viewport Segments API 和 Device Posture API,但考虑到苹果可能有的 ergonomic 和功耗问题,很难想象 Fullscreen API 会被启用。
当然,尽管粉丝们(说实话包括我)想要假装不是这样,确实有一个完整的优秀 Android 折叠手机生态系统。所以让我们在我手边的一个 Pixel 9 Pro Fold 模拟器上试试……运行 Chromium 157……
![]()
不行。尽管 CSS 媒体查询报告了正确的姿态和分段,Chromium 只在上半部分显示全屏内容。下半部分被裁剪,故意如此。5
所以。在 iPhone Duo 和 Pixel Fold 上,Netflix UI 仍然只是一个梦想。
哦好吧。我仍然很高兴我们做得相当接近。在这一切结束时?这无论如何变成了一篇 Video.js v10 发布文章。我喜欢我们新的可组合架构让我能够想象一个视频播放器,并直接用一些简单的 HTML/CSS 构建它。相当不错。
脚注
-
好奇的话,路径是“应用”>“Safari”>“高级”>“功能标志”。没错,这个设置确实存在,只是被奇怪地埋在屏幕底部一个巨大空隙的下方。↩
-
我可以重新定位现有的控件,但为了这个演示,在 DOM 里复制这些东西更简单。↩
-
完全坦白。并非一切都如我所愿。在定位顶部内容时,
bottom: env(viewport-segment-bottom 0 0)把视频正好放在了接缝上。而在定位控件时,height: env(viewport-segment-height 0 1)让内容远远超出了屏幕底部。不知道为什么。如果你知道我漏掉了什么,请告诉我!↩ -
理论上,这说得通。你只希望
<video>出现在上半部分,这样它就不会跨越接缝。但在实践中,也许 Chromium 可以像 WebKit 似乎已经做的那样,只重新定位<video>,同时让整个全屏容器跨越两个部分。也许我该给 Chromium 提个 PR……↩
来源:Hacker News · videojs.org