movie-web/src/components/video/controls/ProgressControl.tsx

75 lines
2.1 KiB
TypeScript
Raw Normal View History

2023-01-08 22:29:38 +01:00
import { useCallback, useEffect, useRef, useState } from "react";
2023-01-08 17:51:38 +01:00
import { useVideoPlayerState } from "../VideoContext";
export function ProgressControl() {
const { videoState } = useVideoPlayerState();
const ref = useRef<HTMLDivElement>(null);
2023-01-08 22:29:38 +01:00
const [mouseDown, setMouseDown] = useState<boolean>(false);
const [progress, setProgress] = useState<number>(0);
2023-01-08 17:51:38 +01:00
2023-01-08 22:29:38 +01:00
let watchProgress = `${(
2023-01-08 17:51:38 +01:00
(videoState.time / videoState.duration) *
100
).toFixed(2)}%`;
2023-01-08 22:29:38 +01:00
if (mouseDown) watchProgress = `${progress}%`;
2023-01-08 17:51:38 +01:00
const bufferProgress = `${(
(videoState.buffered / videoState.duration) *
100
).toFixed(2)}%`;
2023-01-08 22:29:38 +01:00
useEffect(() => {
function mouseMove(ev: MouseEvent) {
if (!mouseDown || !ref.current) return;
const rect = ref.current.getBoundingClientRect();
const pos = ((ev.pageX - rect.left) / ref.current.offsetWidth) * 100;
setProgress(pos);
}
function mouseUp(ev: MouseEvent) {
if (!mouseDown) return;
setMouseDown(false);
document.body.removeAttribute("data-no-select");
2023-01-08 17:51:38 +01:00
if (!ref.current) return;
const rect = ref.current.getBoundingClientRect();
2023-01-08 22:29:38 +01:00
const pos = (ev.pageX - rect.left) / ref.current.offsetWidth;
2023-01-08 17:51:38 +01:00
videoState.setTime(pos * videoState.duration);
2023-01-08 22:29:38 +01:00
}
document.addEventListener("mousemove", mouseMove);
document.addEventListener("mouseup", mouseUp);
return () => {
document.removeEventListener("mousemove", mouseMove);
document.removeEventListener("mouseup", mouseUp);
};
}, [mouseDown, videoState]);
const handleMouseDown = useCallback(() => {
setMouseDown(true);
document.body.setAttribute("data-no-select", "true");
}, []);
2023-01-08 17:51:38 +01:00
return (
<div
ref={ref}
className="relative m-1 my-4 h-4 w-48 overflow-hidden rounded-full border border-white bg-denim-100"
2023-01-08 22:29:38 +01:00
onMouseDown={handleMouseDown}
2023-01-08 17:51:38 +01:00
>
<div
className="absolute inset-y-0 left-0 bg-denim-700 opacity-50"
style={{
width: bufferProgress,
}}
/>
<div
className="absolute inset-y-0 left-0 bg-denim-700"
style={{
width: watchProgress,
}}
/>
</div>
);
}