Electron/React视频播放器全屏切换后ESC按键无响应问题求助
解决Electron/React视频播放器全屏后ESC键无响应问题
问题原因
- 全屏模式下,浏览器/Electron默认会捕获ESC键用于退出全屏,导致React组件的键盘事件监听器无法触发。
- React元素默认不可聚焦,全屏后焦点可能转移到浏览器的全屏容器而非你的播放器组件,进而无法触发组件上的
onKeyDown事件。 - App.js中的全局按键监听失效,是因为全屏状态下焦点不在App根元素上,事件无法冒泡到该层级。
解决方案
方案1:让播放器容器可聚焦并手动获取焦点
修改Player.js,给播放器容器添加可聚焦属性,并在切换全屏后手动聚焦容器:
// Player.js const Player = (props) => { const playerContainerRef = useRef(null); const handleFullscreen = () => { if (screenfull.isEnabled) { screenfull.toggle(playerContainerRef.current); // 延迟确保全屏状态生效后,聚焦容器 setTimeout(() => { if (screenfull.isFullscreen) { playerContainerRef.current?.focus(); } }, 100); } }; const handleKeyDown = (e) => { console.log(e.code); if (e.code === 'Escape' && screenfull.isFullscreen) { screenfull.exit(); e.preventDefault(); // 避免默认退出行为重复触发 } }; return ( <div ref={playerContainerRef} onKeyDown={handleKeyDown} tabIndex="-1" // 让div可聚焦,不参与tab导航 style={{ outline: 'none' }} // 移除聚焦时的默认边框 > <div onDoubleClick={handleFullscreen}> <video /> </div> </div> ); };
方案2:监听全局document键盘事件(更可靠)
直接在Player.js中监听document的键盘事件,不受焦点影响:
// Player.js const Player = (props) => { const playerContainerRef = useRef(null); const handleFullscreen = () => { if (screenfull.isEnabled) { screenfull.toggle(playerContainerRef.current); } }; // 挂载时添加全局键盘监听,卸载时移除 useEffect(() => { const handleGlobalKeyDown = (e) => { if (e.code === 'Escape' && screenfull.isFullscreen) { screenfull.exit(); } }; document.addEventListener('keydown', handleGlobalKeyDown); return () => { document.removeEventListener('keydown', handleGlobalKeyDown); }; }, []); return ( <div ref={playerContainerRef}> <div onDoubleClick={handleFullscreen}> <video /> </div> </div> ); };
方案3:修复App.js全局监听失效问题
将App.js中的按键监听改为绑定到document,而非组件元素:
// App.js useEffect(() => { const handleKeyDown = (e) => { e.preventDefault(); switch (e.code) { case 'Space': refs.playerRef.current?.play(); break; case 'ArrowLeft': refs.playerRef.current?.seekBackward(); break; case 'ArrowRight': refs.playerRef.current?.seekForward(); break; case 'NumpadAdd': refs.playerRef.current?.increaseSpeed(); break; case 'NumpadSubtract': refs.playerRef.current?.decreaseSpeed(); break; case 'Escape': if (screenfull.isFullscreen) { screenfull.exit(); } console.log('Pressed ESC'); break; default: break; } }; document.addEventListener('keydown', handleKeyDown); return () => { document.removeEventListener('keydown', handleKeyDown); }; }, []);
内容的提问来源于stack exchange,提问作者fr0zie
相关产品推荐
相关产品推荐

