improved background video behavior - when loop disabled the video plays once and stops in the last frame
This commit is contained in:
parent
b66bced6ab
commit
fe82dbb318
@ -46,7 +46,7 @@ const CanvasBackground: React.FC<CanvasBackgroundProps> = ({
|
||||
videoEndTime = null,
|
||||
}) => {
|
||||
// Use background video playback hook for custom start/end time handling
|
||||
const { videoRef } = useBackgroundVideoPlayback({
|
||||
const { videoRef, shouldBlockAutoplay } = useBackgroundVideoPlayback({
|
||||
videoUrl: backgroundVideoUrl,
|
||||
autoplay: videoAutoplay,
|
||||
loop: videoLoop,
|
||||
@ -55,6 +55,9 @@ const CanvasBackground: React.FC<CanvasBackgroundProps> = ({
|
||||
endTime: videoEndTime,
|
||||
});
|
||||
|
||||
// Block autoplay if video already played this session (when loop=false)
|
||||
const effectiveAutoplay = videoAutoplay && !shouldBlockAutoplay;
|
||||
|
||||
const handleLoad = () => {
|
||||
onBackgroundReady?.();
|
||||
};
|
||||
@ -117,7 +120,7 @@ const CanvasBackground: React.FC<CanvasBackgroundProps> = ({
|
||||
key={`bg_video_${backgroundVideoUrl}`}
|
||||
className='absolute inset-0 z-1 h-full w-full object-contain'
|
||||
src={backgroundVideoUrl}
|
||||
autoPlay={videoAutoplay}
|
||||
autoPlay={effectiveAutoplay}
|
||||
loop={useNativeLoop}
|
||||
muted={videoMuted}
|
||||
playsInline
|
||||
|
||||
@ -3,11 +3,18 @@
|
||||
*
|
||||
* Manages background video playback with custom start/end times.
|
||||
* Follows patterns from useTransitionPlayback for video time control.
|
||||
*
|
||||
* When loop is disabled, videos are tracked per-session so they only play once
|
||||
* and show the last frame on subsequent page visits (until browser refresh).
|
||||
*/
|
||||
|
||||
import { useEffect, useRef, useCallback, type RefObject } from 'react';
|
||||
import { logger } from '../lib/logger';
|
||||
|
||||
// Session-scoped tracking of videos that have finished playing (when loop=false)
|
||||
// Key: videoUrl, cleared on browser refresh
|
||||
const playedVideos = new Set<string>();
|
||||
|
||||
export interface UseBackgroundVideoPlaybackOptions {
|
||||
/** URL of the video to play */
|
||||
videoUrl?: string;
|
||||
@ -26,6 +33,8 @@ export interface UseBackgroundVideoPlaybackOptions {
|
||||
export interface UseBackgroundVideoPlaybackResult {
|
||||
/** Ref to attach to the video element */
|
||||
videoRef: RefObject<HTMLVideoElement | null>;
|
||||
/** Whether autoplay should be blocked (video already played this session) */
|
||||
shouldBlockAutoplay: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,6 +65,9 @@ export function useBackgroundVideoPlayback({
|
||||
endTime = null,
|
||||
}: UseBackgroundVideoPlaybackOptions): UseBackgroundVideoPlaybackResult {
|
||||
const videoRef = useRef<HTMLVideoElement | null>(null);
|
||||
|
||||
// Block autoplay if video already played this session (only when loop=false)
|
||||
const shouldBlockAutoplay = !loop && videoUrl ? playedVideos.has(videoUrl) : false;
|
||||
// Store current values in refs for event handlers to access
|
||||
const startTimeRef = useRef(startTime);
|
||||
const endTimeRef = useRef(endTime);
|
||||
@ -174,7 +186,35 @@ export function useBackgroundVideoPlayback({
|
||||
video.muted = muted;
|
||||
}, [muted]);
|
||||
|
||||
return { videoRef };
|
||||
// Session-scoped "play once" behavior when loop is disabled
|
||||
// Videos that have already played show last frame on revisit
|
||||
useEffect(() => {
|
||||
const video = videoRef.current;
|
||||
if (!video || !videoUrl || loop) return;
|
||||
|
||||
// If video already played this session, show last frame
|
||||
if (playedVideos.has(videoUrl)) {
|
||||
const showLastFrame = () => {
|
||||
video.currentTime = video.duration - 0.01;
|
||||
video.pause();
|
||||
};
|
||||
if (video.readyState >= 1) {
|
||||
showLastFrame();
|
||||
} else {
|
||||
video.addEventListener('loadedmetadata', showLastFrame, { once: true });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark video as played when it ends
|
||||
const handleEnded = () => {
|
||||
playedVideos.add(videoUrl);
|
||||
};
|
||||
video.addEventListener('ended', handleEnded);
|
||||
return () => video.removeEventListener('ended', handleEnded);
|
||||
}, [videoUrl, loop]);
|
||||
|
||||
return { videoRef, shouldBlockAutoplay };
|
||||
}
|
||||
|
||||
export default useBackgroundVideoPlayback;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user