6 changed files with 124 additions and 28 deletions
@ -0,0 +1,24 @@ |
|||||||
|
import { BackdropControl } from "./controls/BackdropControl"; |
||||||
|
import { FullscreenControl } from "./controls/FullscreenControl"; |
||||||
|
import { LoadingControl } from "./controls/LoadingControl"; |
||||||
|
import { PauseControl } from "./controls/PauseControl"; |
||||||
|
import { ProgressControl } from "./controls/ProgressControl"; |
||||||
|
import { TimeControl } from "./controls/TimeControl"; |
||||||
|
import { VolumeControl } from "./controls/VolumeControl"; |
||||||
|
import { VideoPlayer, VideoPlayerProps } from "./VideoPlayer"; |
||||||
|
|
||||||
|
export function DecoratedVideoPlayer(props: VideoPlayerProps) { |
||||||
|
return ( |
||||||
|
<VideoPlayer autoPlay={props.autoPlay}> |
||||||
|
<BackdropControl> |
||||||
|
<PauseControl /> |
||||||
|
<FullscreenControl /> |
||||||
|
<ProgressControl /> |
||||||
|
<VolumeControl /> |
||||||
|
<LoadingControl /> |
||||||
|
<TimeControl /> |
||||||
|
</BackdropControl> |
||||||
|
{props.children} |
||||||
|
</VideoPlayer> |
||||||
|
); |
||||||
|
} |
@ -0,0 +1,53 @@ |
|||||||
|
import { useCallback, useRef, useState } from "react"; |
||||||
|
import { useVideoPlayerState } from "../VideoContext"; |
||||||
|
|
||||||
|
interface BackdropControlProps { |
||||||
|
children?: React.ReactNode; |
||||||
|
} |
||||||
|
|
||||||
|
export function BackdropControl(props: BackdropControlProps) { |
||||||
|
const { videoState } = useVideoPlayerState(); |
||||||
|
const [moved, setMoved] = useState(false); |
||||||
|
const timeout = useRef<ReturnType<typeof setTimeout> | null>(null); |
||||||
|
|
||||||
|
const handleMouseMove = useCallback(() => { |
||||||
|
setMoved(true); |
||||||
|
if (timeout.current) clearTimeout(timeout.current); |
||||||
|
timeout.current = setTimeout(() => { |
||||||
|
setMoved(false); |
||||||
|
timeout.current = null; |
||||||
|
}, 3000); |
||||||
|
}, [timeout, setMoved]); |
||||||
|
|
||||||
|
const handleClick = useCallback(() => { |
||||||
|
if (videoState.isPlaying) videoState.pause(); |
||||||
|
else videoState.play(); |
||||||
|
}, [videoState]); |
||||||
|
|
||||||
|
const showUI = moved || videoState.isPaused; |
||||||
|
|
||||||
|
return ( |
||||||
|
<div |
||||||
|
className={`absolute inset-0 ${!showUI ? "cursor-none" : ""}`} |
||||||
|
onMouseMove={handleMouseMove} |
||||||
|
onClick={handleClick} |
||||||
|
> |
||||||
|
<div |
||||||
|
className={`absolute inset-0 bg-black bg-opacity-20 transition-opacity duration-200 ${ |
||||||
|
!showUI ? "!opacity-0" : "" |
||||||
|
}`}
|
||||||
|
/> |
||||||
|
<div |
||||||
|
className={`absolute inset-x-0 bottom-0 h-[30%] bg-gradient-to-t from-black to-transparent opacity-75 transition-opacity duration-200 ${ |
||||||
|
!showUI ? "!opacity-0" : "" |
||||||
|
}`}
|
||||||
|
/> |
||||||
|
<div |
||||||
|
className={`absolute inset-x-0 top-0 h-[30%] bg-gradient-to-b from-black to-transparent opacity-75 transition-opacity duration-200 ${ |
||||||
|
!showUI ? "!opacity-0" : "" |
||||||
|
}`}
|
||||||
|
/> |
||||||
|
<div className="absolute inset-0">{showUI ? props.children : null}</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
Loading…
Reference in new issue