I have a React project where I'm having a slider between 0 and 700 and depending on which step is chosen it gets value between 1
and 8
(so 700 is obviously 8).
<div className={styles.slider_container}>
<input type='range' className={styles.slider} step={100} min={0} max={700} value={value} onChange={(e) => setValue(parseInt(e.target.value))} />
</div>
I also have an frames
array which consists of bunch of objects which look like:
const [frames, setFrames] = useState([
{
id: 1,
title: 'Touch',
start: 0,
idle: 5.82,
end: 7.10,
},
{
id: 2,
title: 'Display',
start: 7.11,
idle: 8.5,
end: 10.12,
},
...
];
and I call my VideoPlayer
component as:
<div className={styles.content}>
<VideoPlayer frames={frames} currentComponent={selectedComponent} prevComponent={prevComponent} startTime={frames.find((item) => item.id === selectedComponent).start} endTime={frames.find((item) => item.id === selectedComponent).end} idleTime={frames.find((item) => item.id === selectedComponent).idle} />
</div>
VideoPlayer
component is just using react-video library to display the video and play/pause/seek through it. and it is just like:
const [currentTime, setCurrentTime] = useState(startTime);
const playerRef = useRef(null);
useEffect(() => {
if (currentTime >= idleTime) {
playerRef.current.pause();
}
}, [currentTime]);
useEffect(() => {
if (prevComponent) {
if (prevComponent < currentComponent) {
const time = (frames.find(item => item.id === prevComponent).end); // endTime of previous component;
if (currentTime <= time) {
playerRef.current.play();
if (time - currentTime <= 0.3) {
playerRef.current.pause();
playerRef.current.seek(startTime);
playerRef.current.play();
}
}
}
}
}, [currentTime, currentComponent]);
useEffect(() => {
if (prevComponent > currentComponent) {
playerRef.current.seek(startTime);
playerRef.current.play();
}
}, [currentComponent]);
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>
It works fine with going forward (I mean from step 2 to step 3 or step 4), but I have a problem in
useEffect(() => {
if (prevComponent > currentComponent) {
playerRef.current.seek(startTime);
playerRef.current.play();
}
}, [currentComponent]);
where if I select a component (or step) 2 after step 3 (if we go back), it should play the video till endTime of the prevComponent
and then just back to startTime
of currentComponent
and continue playing till idleTime
of the currentComponent
.
I would apply the while
loop to if (prevComponent > currentComponent)
condition, so it would just play the video till the difference between time
and currentTime
is less or equal to zero, if so, just break out from the loop and then use seek()
function to jump to another frame/time you want.
useEffect(() => {
if (prevComponent > currentComponent) {
while(time - currentTime > 0) {
playerRef.current.play();
}
playerRef.current.seek(startTime);
}
}, [currentTime, currentComponent]);