React中react-video回退时分段播放逻辑异常问题
解决React视频播放器回退逻辑缺失问题
当前正向切换组件(如从步骤2到3)功能正常,但回退时(如从步骤3到2),未实现先播放至前一个组件的endTime,再跳转到当前组件的startTime并播放至其idleTime的预期逻辑,而是直接跳转到当前组件的startTime开始播放。
问题原因
负责回退逻辑的useEffect仅执行了直接跳转和播放操作,完全跳过了"播放前组件剩余部分至endTime"的步骤:
useEffect(() => { if (prevComponent > currentComponent) { playerRef.current.seek(startTime); playerRef.current.play(); } }, [currentComponent]);
解决方案
通过添加过渡状态跟踪,分阶段执行回退流程:
修改后的VideoPlayer组件代码
import { useState, useRef, useEffect } from 'react'; import { Player, ControlBar } from 'react-video'; const VideoPlayer = ({ frames, currentComponent, prevComponent, startTime, endTime, idleTime }) => { const [currentTime, setCurrentTime] = useState(startTime); const playerRef = useRef(null); // 新增状态:标记是否处于回退过渡阶段,以及过渡目标时间(前组件的endTime) const [backTransition, setBackTransition] = useState({ isActive: false, targetEndTime: 0 }); useEffect(() => { // 正常播放到idleTime暂停的逻辑保留 if (currentTime >= idleTime && !backTransition.isActive) { playerRef.current.pause(); } // 处理回退过渡:到达前组件的endTime后,跳转至当前组件start并播放 if (backTransition.isActive && currentTime >= backTransition.targetEndTime) { playerRef.current.pause(); playerRef.current.seek(startTime); playerRef.current.play(); // 结束过渡状态 setBackTransition({ isActive: false, targetEndTime: 0 }); } }, [currentTime, idleTime, backTransition, startTime]); // 正向切换逻辑保留 useEffect(() => { if (prevComponent && prevComponent < currentComponent) { const prevEndTime = frames.find(item => item.id === prevComponent).end; if (currentTime <= prevEndTime) { playerRef.current.play(); if (prevEndTime - currentTime <= 0.3) { playerRef.current.pause(); playerRef.current.seek(startTime); playerRef.current.play(); } } } }, [currentTime, currentComponent, prevComponent, frames, startTime]); // 修改回退逻辑:启动过渡,先播放至前组件的endTime useEffect(() => { if (prevComponent && prevComponent > currentComponent) { const prevFrame = frames.find(item => item.id === prevComponent); const prevEndTime = prevFrame.end; // 如果当前时间已经超过前组件的endTime,直接跳转 if (currentTime >= prevEndTime) { playerRef.current.seek(startTime); playerRef.current.play(); return; } // 启动回退过渡:先播放到前组件的endTime setBackTransition({ isActive: true, targetEndTime: prevEndTime }); playerRef.current.play(); } }, [currentComponent, prevComponent, frames, currentTime, startTime]); return ( <Player ref={playerRef} autoPlay startTime={0} muted={true} onTimeUpdate={(e) => { setCurrentTime(parseFloat(e.target.currentTime)); }} > <source src="./video.mp4" style={{ height: '100vh' }} /> <ControlBar autoHide={false} disableCompletely={true} disableDefaultControls={true} /> </Player> ); }; export default VideoPlayer;
关键逻辑说明
backTransition状态:用于标记是否处于回退过渡流程中,同时存储需要播放到的前组件endTime,避免和正常播放逻辑冲突。- 回退触发逻辑:检测到回退操作时,先判断当前时间是否已超过前组件的endTime,若未超过则启动过渡,播放至该时间点;若已超过则直接跳转至当前组件的startTime。
- 过渡阶段处理:在
currentTime的监听逻辑中,当到达过渡目标时间时,自动跳转至当前组件的startTime并开始播放,同时结束过渡状态,恢复正常播放逻辑。
内容的提问来源于stack exchange,提问作者user22883124
相关产品推荐
相关产品推荐

