import React, { FC, useContext, useEffect, useMemo, useState } from 'react'; import { rangeMap } from '../utils/rangeMap'; import { ArticleRectContext } from '../provider/ArticleRectContext'; import { ScrollPlaybackVideoManager, ScrollPlaybackFrameData } from '@cntrl-site/sdk'; type PlaybackParams = { from: number, to: number }; interface Props { sectionId: string; src: string; playbackParams: PlaybackParams | null; style?: React.CSSProperties; className: string; scrollPlaybackFrameData?: ScrollPlaybackFrameData | null; frameBaseUrl?: string; } export const ScrollPlaybackVideo: FC = ({ sectionId, src, playbackParams, style, className, scrollPlaybackFrameData, frameBaseUrl }) => { const [containerElement, setContainerElement] = useState(null); const [time, setTime] = useState(0); const articleRectObserver = useContext(ArticleRectContext); const hasServerFrames = scrollPlaybackFrameData?.status === 'ready' && scrollPlaybackFrameData.batchId && scrollPlaybackFrameData.frameCount && scrollPlaybackFrameData.frameRate && scrollPlaybackFrameData.frameFormat && frameBaseUrl; useEffect(() => { if (!playbackParams || !articleRectObserver) return; const from = playbackParams.from; const to = playbackParams.to; return articleRectObserver.on('scroll', () => { const scrollPos = articleRectObserver.getSectionScroll(sectionId); const nextTime = rangeMap(scrollPos, from, to, 0, 1, true); setTime(toFixed(nextTime)); }); }, [sectionId, playbackParams?.from, playbackParams?.to, articleRectObserver]); const scrollVideoManager = useMemo(() => { if (!containerElement) return null; const manager = new ScrollPlaybackVideoManager({ src, videoContainer: containerElement, ...(hasServerFrames ? { frameData: { batchId: scrollPlaybackFrameData.batchId!, frameCount: scrollPlaybackFrameData.frameCount!, frameRate: scrollPlaybackFrameData.frameRate!, frameFormat: scrollPlaybackFrameData.frameFormat! }, frameBaseUrl } : {}) }); return manager; }, [containerElement, src, hasServerFrames, frameBaseUrl]); useEffect(() => { return () => { scrollVideoManager?.destroy(); }; }, [scrollVideoManager]); useEffect(() => { if (scrollVideoManager && time >= 0 && time <= 1) { scrollVideoManager.setTargetTimePercent(time); } }, [time, scrollVideoManager]); return
; }; function toFixed(num: number) { return Number(num.toFixed(3)); }