From 67d3c02a89cb170fc1819ae49ef7ba08f1d8305c Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 16 Jun 2021 20:13:32 +0200 Subject: draggable slides --- pages/editor.tsx | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++----- timeline.ts | 1 + 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/pages/editor.tsx b/pages/editor.tsx index 1f79699..0da9a0d 100644 --- a/pages/editor.tsx +++ b/pages/editor.tsx @@ -26,6 +26,7 @@ import PlaySkipIconAni from '../components/play-skip'; import Selection from '../components/selection'; var keyframeInAnimations: { [key: string]: { x: number; y: number; }; } = {}; +var slideAPIs: { [key: string]: any; }[] = []; var player = new TimedVideoPlayer(); var useWorkingTimeline = create((set, get) => ({ @@ -108,6 +109,8 @@ function TimelineKeyframe(props: { config: { mass: 0.5, tension: 500, friction: 20 }, })); + slideAPIs[props.slide.id] = api; + useEffect(() => { setFirstRender(false); var beginAnimation = keyframeInAnimations[props.slide.id]; @@ -318,15 +321,14 @@ function TimelineEditor(props: { window.addEventListener('resize', onresize); }, []); + // timeline scrubber var scrubberDragRef = useRef(null); - var [scrubberPos, scrubberSpring] = useSpring( () => ({ frame: 0, config: { mass: 0.5, tension: 500, friction: 20 }, }), ); - useDrag(({ xy: [x, _y] }) => { var frame = Math.max(0, Math.round(getFrameAtOffset(x - 240, timelineZoom)) - 1); setFrame(frame); @@ -337,6 +339,7 @@ function TimelineEditor(props: { } }, { domTarget: scrubberDragRef, eventOptions: { passive: false } }); + // slide placement ghost var [ghost, ghostApi] = useSpring(() => ({ x: 0, y: 0, @@ -351,6 +354,7 @@ function TimelineEditor(props: { }); }, []); + // selection var [selectionActive, setSelectionActive] = useState(false); var [selectionPlaced, setSelectionPlaced] = useState(false); var [selectionHidden, setSelectionHidden] = useState(true); @@ -368,7 +372,45 @@ function TimelineEditor(props: { widthOffset: 0, config: { mass: 0.5, tension: 500, friction: 20 }, })); + var selectionAreaRef = useRef(null); var selectionRef = useRef(null); + var [selection, setSelection] = useState([]); + useDrag(({ movement: [x, _y], last }) => { + if (!selectionPlaced) return; + if (selection.length < 1) return; + var frameOffset = Math.round(x / zoomToPx(timelineZoom)); + selection.forEach((slide: anySlide) => { + var api = slideAPIs[slide.id]; + switch (slide.type as slideTypes | 'loopBegin') { + case 'loopBegin': { + if (!api) break; + var loop = workingTimeline.find((s: anySlide) => s.id == slide.id) as loopSlide; + var begin = loop.beginFrame + frameOffset; + api.start({ begin }); + + if (last) { + loop.beginFrame = begin; + refreshWorkingTimline(); + } + + break; + } + default: { + if (!api) break; + var frame = slide.frame + frameOffset; + api.start({ frame }); + + if (last) { + workingTimeline.find((s: anySlide) => s.id == slide.id).frame = frame; + refreshWorkingTimline(); + } + } + } + if (last) return; + var selectionFrame = selection[0].frame; + selectionPosAPI.start({ startingFrame: selectionFrame + frameOffset }); + }); + }, { domTarget: selectionRef, eventOptions: { passive: false } }); useDrag(({ xy: [x, y], initial: [bx, by], first, last, movement: [ox, oy] }) => { if (props.selectedTool != 'cursor') return; var minDistance = 5; // minimal drag distance in pixels to register selection @@ -383,6 +425,8 @@ function TimelineEditor(props: { startOffset: 0, widthOffset: 0, }); + selection = []; + setSelection(selection); var timelineInner = document.querySelector('.timeline .timelineInner'); var timelineRects = timelineInner.getBoundingClientRect(); @@ -416,9 +460,11 @@ function TimelineEditor(props: { if (slide.type != 'loop') continue; var beginFrame = (slide as loopSlide).beginFrame; expandedTimeline.splice(i, 0, new loopBeginSlide(beginFrame)); + expandedTimeline[i].id = expandedTimeline[i + 1].id; i++; } - var keyframesInSelection = expandedTimeline.filter((slide: anySlide) => + + var keyframesInSelection = expandedTimeline.filter(slide => slide.frame >= Math.floor(startingFrame) && slide.frame <= Math.ceil(endingFrame) ); @@ -427,6 +473,9 @@ function TimelineEditor(props: { return; } + selection = keyframesInSelection; + setSelection(selection); + var left = keyframesInSelection[0]; var right = keyframesInSelection[keyframesInSelection.length - 1]; @@ -446,7 +495,7 @@ function TimelineEditor(props: { setSelectionPlaced(true); } } - }, { domTarget: selectionRef, eventOptions: { passive: false } }); + }, { domTarget: selectionAreaRef, eventOptions: { passive: false } }); return <> -
+
{workingTimeline.map((slide: anySlide) => )}