diff options
-rw-r--r-- | pages/editor.tsx | 26 | ||||
-rw-r--r-- | pages/present.tsx | 8 |
2 files changed, 28 insertions, 6 deletions
diff --git a/pages/editor.tsx b/pages/editor.tsx index 8f0637b..5f29ddf 100644 --- a/pages/editor.tsx +++ b/pages/editor.tsx @@ -52,9 +52,9 @@ var useFrame = create(set => ({ function TimelineEditor(props: { player: TimedVideoPlayer; }) { - var keyframes = props.player?.timeline?.slides.map(slide => + var keyframes = props.player?.timeline?.slides.map((slide, index) => <div className='frame posabs' style={{ '--frame': slide.frame.toString() } as CSSProperties}> - <div className='keyframeWrapper posabs abscenterh'> + <div className={'keyframeWrapper posabs abscenterh keyframe-index-' + index}> {slide.type == 'loop' ? <Loop length={slide.frame - (slide as loopSlide).beginFrame} /> : <SlideKeyframe type={slide.type} />} @@ -71,13 +71,27 @@ function TimelineEditor(props: { var timelineZoom = getTimelineZoom((st: any) => st.zoom); useEffect(() => { - var canvas = document.getElementById('timeScaleCanvas') as HTMLCanvasElement; - var ctx = canvas.getContext('2d'); - props.player.addEventListener('TimedVideoPlayerOnFrame', (event: CustomEvent) => { setFrame(event.detail); scrubberSpring.start({ frame: event.detail }); }); + }, []); + + useEffect(() => { + props.player.addEventListener('TimedVideoPlayerSlide', (event: CustomEvent) => { + document.querySelectorAll('.keyframes .keyframeWrapper').forEach(el => { + el.classList.remove('current'); + if (el.classList.contains(`keyframe-index-${event.detail}`)) { + el.classList.add('current'); + } + }); + }); + }, []); + + // timeline canvas stuff + useEffect(() => { + var canvas = document.getElementById('timeScaleCanvas') as HTMLCanvasElement; + var ctx = canvas.getContext('2d'); var css = (varname: string) => getComputedStyle(document.body).getPropertyValue(varname).trim(); var baseColor = css('--c100'); @@ -166,7 +180,7 @@ function TimelineEditor(props: { var frame = Math.max(0, Math.round(getFrameAtOffset(x - 240, timelineZoom)) - 1); setFrame(frame); scrubberSpring.start({ frame }); - if(props.player.player) { + if (props.player.player) { var player = props.player.player; player.currentTime = props.player.frameToTimestamp(frame + 1); } diff --git a/pages/present.tsx b/pages/present.tsx index b8564b4..f5955fc 100644 --- a/pages/present.tsx +++ b/pages/present.tsx @@ -86,6 +86,8 @@ export class TimedVideoPlayer { case 'delay': { this.player.playbackRate = 0; this.slide++; + var event = new CustomEvent('TimedVideoPlayerSlide', { detail: this.slide }); + this.dispatchEvent(event); setTimeout(() => { this.player.playbackRate = this.getPlaybackSpeed(this.slide - 1); }, (slide as delaySlide).delay); @@ -93,6 +95,8 @@ export class TimedVideoPlayer { } case 'speedChange': { this.slide++; + var event = new CustomEvent('TimedVideoPlayerSlide', { detail: this.slide }); + this.dispatchEvent(event); this.player.playbackRate = this.framerate / (slide as speedChangeSlide).newFramerate; break; } @@ -182,6 +186,8 @@ export class TimedVideoPlayer { if (!this.registeredEventListeners) return; this.slide++; + var event = new CustomEvent('TimedVideoPlayerSlide', { detail: this.slide }); + this.dispatchEvent(event); var slide = this.timeline.slides[this.slide]; @@ -196,6 +202,8 @@ export class TimedVideoPlayer { if (!this.registeredEventListeners) return; this.slide = Math.max(this.slide - 1, -1); + var event = new CustomEvent('TimedVideoPlayerSlide', { detail: this.slide }); + this.dispatchEvent(event); var slide = this.timeline.slides[this.slide]; if (!slide) return; |