【xgplayer】xgplayer全屏模式优化实战 | 解决CSS全屏与播放器全屏切换冲突
1. 理解xgplayer全屏冲突的核心问题第一次用xgplayer做移动端视频项目时我就被这个全屏切换的坑折磨得不轻。明明在PC端测试好好的功能到了手机上就出现视频凭空消失的灵异现象。后来发现这其实是CSS全屏和播放器原生全屏两种模式切换时的典型冲突。具体表现是这样的当你先用CSS全屏模式观看视频这种模式特别适合9:16的竖屏视频然后再切换到播放器自带的原生全屏模式时缩小窗口后视频容器会神秘失踪只留下孤零零的控制按钮。这是因为两种全屏模式对DOM元素的处理方式不同CSS全屏通过修改元素的class实现视觉填充不改变DOM结构原生全屏浏览器API会将元素移出当前文档流放入全屏专用层// 问题重现代码示例 player.on(exitFullscreen, () { // 退出原生全屏时CSS全屏元素可能已经不在预期位置 videoContainer.style.display none; // 这就是视频消失的原因 });2. 两种全屏模式的本质区别要彻底解决这个问题得先明白两种全屏的技术原理。去年我做短视频项目时就因为这个知识点没吃透导致上线后出现大量用户投诉。CSS全屏模式通过绝对定位固定宽高模拟全屏效果优点保持DOM结构不变适合特殊比例视频缺点地址栏等浏览器UI仍然可见原生全屏模式调用element.requestFullscreen()API优点真正的全屏体验隐藏所有浏览器UI缺点会改变元素层级关系导致CSS定位失效/* CSS全屏的典型实现 */ .css-fullscreen { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 9999; }3. 完整解决方案实现步骤经过三个项目的实战验证我总结出这个稳定可用的解决方案。关键是要在两种全屏模式切换时正确处理按钮的显隐状态和元素层级关系。3.1 基础配置准备首先确保正确导入xgplayer的必要模块。这里有个坑要注意不同版本的导入路径可能不同建议直接指定完整路径。import Player from xgplayer/dist/simple_player; import cssFullscreen from xgplayer/dist/controls/cssFullscreen; import { toggleClass } from xgplayer/src/utils/util; const playerOpts { id: player, url: video.mp4, cssFullscreen: true, // 必须开启此选项 controlPlugins: [ cssFullscreen // 添加CSS全屏按钮 ] };3.2 事件监听与状态同步核心逻辑在于这两个事件监听器。我在实际项目中发现必须在ready事件之后才能安全操作DOM元素否则可能找不到按钮节点。player.once(ready, () { const fullScrBtn document.querySelector(#player .xgplayer-fullscreen); // 进入CSS全屏时隐藏原生全屏按钮 player.on(requestCssFullscreen, () { toggleClass(fullScrBtn, hide); // 额外保险强制设置display属性 fullScrBtn.style.display none; }); // 退出CSS全屏时恢复按钮 player.on(exitCssFullscreen, () { toggleClass(fullScrBtn, hide); fullScrBtn.style.display ; }); });3.3 CSS样式加固光靠JS控制还不够稳定我建议加上这些CSS规则作为双重保障。特别注意scoped样式的问题这在Vue项目中很常见。#player .xgplayer-fullscreen.hide { display: none !important; visibility: hidden !important; } /* 处理移动端特殊场景 */ media (orientation: portrait) { #player .xgplayer-css-fullscreen { z-index: 10000; } }4. 移动端特殊场景处理在最近的一个跨平台项目中我发现iOS设备上还有额外的问题需要处理。特别是当设备旋转时全屏状态可能会异常退出。4.1 横竖屏适配方案针对不同比例的视频需要动态调整全屏策略。这是我的经验方案16:9视频优先使用原生全屏9:16视频强制使用CSS全屏其他比例根据设备方向自动选择// 检测视频比例决定全屏模式 function checkVideoRatio(url) { return new Promise((resolve) { const video document.createElement(video); video.src url; video.onloadedmetadata () { const ratio video.videoWidth / video.videoHeight; resolve(ratio 1 ? native : css); }; }); }4.2 防止意外退出的技巧在orientationchange事件中添加这些处理逻辑可以避免很多奇怪的bugwindow.addEventListener(orientationchange, () { if(player.isFullscreen) { // 保持全屏状态 player.exitFullscreen(); setTimeout(() player.requestFullscreen(), 100); } });5. 进阶优化建议经过多个项目迭代我总结出这些提升用户体验的技巧5.1 平滑过渡动画突然消失的按钮会让用户困惑添加过渡效果会更自然#player .xgplayer-fullscreen { transition: opacity 0.3s ease; } #player .xgplayer-fullscreen.hide { opacity: 0; }5.2 状态持久化方案使用localStorage记住用户最后一次使用的全屏模式player.on(requestFullscreen, () { localStorage.setItem(preferredFullscreen, native); }); player.on(requestCssFullscreen, () { localStorage.setItem(preferredFullscreen, css); });5.3 性能优化技巧全屏切换时注意这些性能陷阱避免频繁重排重绘使用will-change提前告知浏览器对视频解码器做预热处理// 预加载解码器 player.video.addEventListener(loadeddata, () { player.video.pause(); player.video.currentTime 0.1; });6. 常见问题排查指南遇到问题时可以按照这个检查清单逐步排查元素选择器是否正确使用Chrome开发者工具检查按钮的实际class名事件触发顺序问题在控制台输出各事件的触发时间戳z-index层级冲突使用3D视图检查元素堆叠关系移动端浏览器兼容性特别注意iOS的PWA模式下全屏API的限制// 调试事件监听 player.on(requestCssFullscreen, () { console.time(cssFullscreen); }); player.on(exitCssFullscreen, () { console.timeEnd(cssFullscreen); });7. 实际项目中的经验分享去年开发教育类APP时我们遇到了一个棘手情况当老师在PPT全屏模式下点击视频全屏时会导致PPT布局错乱。最终解决方案是检测到PPT处于全屏状态时禁用视频原生全屏使用CSS全屏时动态调整视频层级添加中间过渡层防止z-index穿透// PPT全屏时的特殊处理 document.addEventListener(pptFullscreenChange, (e) { if(e.detail.isFullscreen) { playerConfig.cssFullscreen true; player.updateConfig(playerConfig); } });这个案例告诉我全屏交互不能孤立考虑必须放在具体业务场景中验证。现在我的团队都会在需求阶段就明确全屏策略避免后期返工。