蘑菇视频官网小窗打开时横竖屏我整理了3个场景对应解法
蘑菇视频官网遇到“小窗(画中画)打开时横屏/竖屏显示不对”的问题,常见表现有画面被裁切、黑边、控件位置错位或小窗自动旋转不跟设备方向走。基于实际开发与兼容性考虑,我把常见的三类场景拆出来,并给出可直接落地的解决方案、示例代码与调试要点,便于在官网上快速修复与优化。

一、场景一:小窗保持固定宽高导致横竖屏时画面被裁切或出现黑边 问题描述
-
小窗容器尺寸固定(例如宽高比为16:9),但用户从竖屏切到横屏或反向时,视频被拉伸、裁切或上下出现黑边。 解决思路
-
用响应式尺寸和视频自适应策略(object-fit + 动态调整容器尺寸),在横竖屏切换时按设备视口重计算小窗大小和位置。 实现要点与示例 1) CSS 保证视频自适应: .video-pip { position: fixed; right: 12px; bottom: 12px; width: 320px; /* 初始值,可动态调整 / height: 180px; overflow: hidden; border-radius: 8px; background: #000; } .video-pip video { width: 100%; height: 100%; object-fit: contain; / 或 cover,根据需求选择 */ display: block; }
-
object-fit: contain 会保证全部画面显示(可能有黑边);cover 会填满容器(可能裁切)。根据内容优先级选其一。
2) JS 动态重算尺寸(监听 orientationchange / resize): function adjustPipSize() { const pip = document.querySelector('.video-pip'); const vw = window.innerWidth; const vh = window.innerHeight; // 横屏时放大小窗,竖屏时缩小 if (vw > vh) { pip.style.width = Math.min(420, vw * 0.28) + 'px'; pip.style.height = (parseInt(pip.style.width) * 9 / 16) + 'px'; } else { pip.style.width = Math.min(320, vw * 0.44) + 'px'; pip.style.height = (parseInt(pip.style.width) * 9 / 16) + 'px'; } } window.addEventListener('resize', adjustPipSize); window.addEventListener('orientationchange', adjustPipSize); adjustPipSize();
调试要点
- 测试不同视频纵横比(4:3、16:9、1:1)效果。
- 根据设计决定优先“完整显示画面”还是“填满小窗”。
二、场景二:浏览器/系统进入画中画模式后控件位置或交互异常(例如播放控件消失、拖拽失效) 问题描述
- 使用浏览器原生 Picture-in-Picture(PiP)或自定义小窗时,控件不显示或拖拽不可交互;某些浏览器在 PiP 模式下限制交互。 解决思路
- 优先使用原生 Picture-in-Picture API 管理视频弹窗(兼容支持),在不能使用原生 PiP 时用自定义小窗并补足交互(拖拽、最小化、回到页面)。 实现要点与示例 1) 原生 PiP(尽可能优先): const video = document.querySelector('video'); async function enterPiP() { try { if (document.pictureInPictureElement) { await document.exitPictureInPicture(); return; } await video.requestPictureInPicture(); } catch (e) { // 浏览器不支持或被策略限制,降级使用自定义小窗 enableCustomPip(); } } video.addEventListener('enterpictureinpicture', () => { // 更新 UI 状态 }); video.addEventListener('leavepictureinpicture', () => { // 恢复 UI });
2) 自定义小窗(针对不支持原生 PiP 或需要自定义交互):实现拖拽、最小化、回到页面
- 拖拽:touchstart/touchmove 或 mousedown/mousemove 实现
- 点击回到页面:绑定 click 恢复到原位置或触发全屏播放 3) 控件兼容性注意
- 在 iOS Safari 中 video.requestPictureInPicture 支持较晚,且 iOS 对某些自动播放策略有限制,需处理 user gesture 的约束。
- 在微信内置浏览器、QQ 等“内嵌浏览器”上,可能没有 PiP,使用自定义小窗作为通用方案。
三、场景三:多平台/多浏览器差异导致横竖屏行为不一致(如 iOS、Android、桌面 Chrome) 问题描述
- 同一小窗在不同平台表现差异大:iOS 不允许锁定方向、Android 某些 WebView 自动旋转、桌面无旋转概念但窗口大小变化仍需适配。 解决思路
- 做平台能力检测并使用分支策略:原生能力优先(Screen Orientation API、Picture-in-Picture API),不支持时降级为可控自定义方案;同时借助媒体查询与 visualViewport 提供平滑适配。 实现要点与示例 1) 检测能力与 UserAgent 轻判断: const supportsPiP = !!document.pictureInPictureEnabled; const supportsOrientation = !!screen.orientation && !!screen.orientation.lock; const ua = navigator.userAgent.toLowerCase(); const isWeChat = /micromessenger/.test(ua); const isIOS = /iphone|ipad|ipod/.test(ua);
2) 根据能力选择行为
- supportsPiP:优先调用 requestPictureInPicture
- supportsOrientation && 需要锁定方向:screen.orientation.lock('landscape').catch(()=>{/降级处理/})
- 在 iOS / 微信内置浏览器不支持时:启用自定义小窗并提供显式“回到播放页”按钮
3) 使用 visualViewport 提供更稳健的尺寸信息(尤其在移动软键盘出现时) window.visualViewport && window.visualViewport.addEventListener('resize', () => { // 以 visualViewport.width/height 作为参考重计算小窗 });
测试与上线检查清单(快速)
- 不同设备:iPhone(Safari)、iPad、Android Chrome、Android 微信内置浏览器、桌面 Chrome/Firefox。
- 横屏/竖屏手动切换:观察小窗尺寸、比例、控件显示、拖拽交互。
- PiP API 支持链路:enter/leave 事件能正确触发并同步 UI 状态。
- 用户手势场景:播放/暂停/进入 PiP 是否受用户手势限制(例如静音自动播放的处理)。
- 极端尺寸:超小屏(小于320px)和超大屏(平板横屏)下小窗展示是否合理。
常见坑与建议
- 不要在没有用户交互时强行 requestPictureInPicture(部分浏览器会拒绝或抛出异常)。
- object-fit 选择要基于内容优先:人物类视频优先 contain(完整),场景类视频或背景类可优先 cover。
- 在微信/QQ 等内嵌浏览器做更丰富的降级提示(例如“此浏览器不支持画中画,请使用返回播放”),提升用户体验。
- 对于需要定位精确的控件(如进度条、音量),优先把交互保留在主页面,PiP 只负责播放预览与简单控制(播放/暂停/关闭)。
-
喜欢(11)
-
不喜欢(3)
