Safari浏览器中退出全屏后立即请求全屏的无延迟替代方案咨询
Safari浏览器中退出全屏后立即请求全屏的无延迟替代方案咨询
嘿,我太懂你这种依赖定时器的糟心感了——用个100ms延迟在自己设备上好用,换个性能差点的Safari设备可能就失效,完全不鲁棒。其实咱们可以利用浏览器原生的全屏状态事件来解决,根本不需要猜时间,这才是靠谱的做法:
方案一:监听fullscreenchange事件,同步全屏状态变化
浏览器在进入或退出全屏时都会触发fullscreenchange事件,咱们可以在退出全屏后,等待这个事件确认状态真的变更完成,再发起新的全屏请求。这样完全跟着浏览器的节奏走,没有任何硬编码延迟。
修改你的requestFullScreen函数如下:
const requestFullScreen = async (id?: string) => { if (document.fullscreenElement) { // 先执行退出全屏操作 await document.exitFullscreen(); // 等待全屏状态真正退出的事件通知 await new Promise(resolve => { const handleExitComplete = () => { // 确认当前没有任何全屏元素了 if (!document.fullscreenElement) { document.removeEventListener('fullscreenchange', handleExitComplete); resolve(null); } }; document.addEventListener('fullscreenchange', handleExitComplete); }); } // 现在安全地发起新的全屏请求 if (id) { const targetElement = document.getElementById(id); if (targetElement) { await targetElement.requestFullscreen(); setFullScreenId(id); } } else { await document.documentElement.requestFullscreen(); } };
为什么这个方法靠谱?
- 完全依赖浏览器的原生状态通知,不存在“延迟不够”或“延迟浪费时间”的问题
- 兼容所有支持Fullscreen API的现代浏览器,包括Safari
- 主动移除事件监听器,避免内存泄漏
方案二:用requestAnimationFrame轮询状态(备选方案)
如果你担心某些极端场景下fullscreenchange事件不触发(虽然概率极低),可以用requestAnimationFrame做轻量轮询,检查全屏状态是否真的退出:
const waitForFullscreenExit = async () => { return new Promise(resolve => { const checkExitStatus = () => { if (!document.fullscreenElement) { resolve(null); } else { requestAnimationFrame(checkExitStatus); } }; checkExitStatus(); }); }; // 在requestFullScreen里替换setTimeout为这个函数 if (document.fullscreenElement) { await document.exitFullscreen(); await waitForFullscreenExit(); }
这个方法的好处是不会阻塞主线程,比setInterval更友好,而且轮询的频率和浏览器渲染帧同步,性能开销极小。
额外的小优化
另外,你的exitFullScreen函数里重复调用了await document.exitFullscreen(),其实没必要——第一次await之后,退出操作已经完成了(结合上面的事件监听或轮询的话),可以简化成:
const exitFullScreen = async () => { if (document.fullscreenElement) { await document.exitFullscreen(); // 同样可以用上面的方法等待退出完成,再更新状态 await new Promise(resolve => { const handleExit = () => { if (!document.fullscreenElement) { document.removeEventListener('fullscreenchange', handleExit); resolve(null); } }; document.addEventListener('fullscreenchange', handleExit); }); } setFullScreenId(""); };
这样能确保状态更新和实际全屏状态完全同步,避免出现UI和实际状态不一致的情况。
内容来源于stack exchange
相关产品推荐
相关产品推荐

