From 9a0cb1148039c30b7a001bfca548e4223137ecbb Mon Sep 17 00:00:00 2001 From: lonkaars Date: Sun, 23 May 2021 12:32:44 +0200 Subject: keyframes draggable :tada:g --- pages/editor.tsx | 66 +++++++++++++++++++++++++++------------------------- styles/editor.css | 10 ++++---- timeline.schema.json | 18 +++++++++++++- timeline.ts | 1 + 4 files changed, 58 insertions(+), 37 deletions(-) diff --git a/pages/editor.tsx b/pages/editor.tsx index e1e164a..e3607e6 100644 --- a/pages/editor.tsx +++ b/pages/editor.tsx @@ -2,7 +2,7 @@ import { CSSProperties, ReactNode, useEffect, useRef, useState } from 'react'; import { animated, useSpring, useSprings } from 'react-spring'; import { useDrag } from 'react-use-gesture'; import create from 'zustand'; -import { loopSlide } from '../timeline'; +import { delaySlide, loopSlide, slide, speedChangeSlide } from '../timeline'; import { TimedVideoPlayer } from './present'; import AppBar from '@material-ui/core/AppBar'; @@ -49,41 +49,43 @@ var useFrame = create(set => ({ setFrame: (newFrame: number) => set(() => ({ currentFrame: newFrame })), })); -function TimelineEditor(props: { - player: TimedVideoPlayer; +function TimelineKeyframe(props: { + slide: slide | delaySlide | loopSlide | speedChangeSlide; }) { - var timelineZoom = getTimelineZoom((st: any) => st.zoom); - - var keyframes: Array<{ - html: ReactNode; - id: string; - }> = []; - var [keyframeSprings, _keyframeSpringsAPI] = useSprings( - props.player?.timeline?.slides.length || 0, - i => ({ - frame: props.player.timeline.slides[i].frame, + var ref = useRef(null); + var [spring, api] = useSpring( + () => ({ + frame: props.slide.frame, config: { mass: 0.5, tension: 500, friction: 20 }, }), ); - props.player?.timeline?.slides.forEach((slide, index) => { - var id = 'frame' + index; - var html = -
- {slide.type == 'loop' - ? - : } -
-
; - keyframes[index] = { - html, - id, - }; - }); + var timelineZoom = getTimelineZoom((st: any) => st.zoom); + + useDrag(({ xy: [x, _y] }) => { + var frame = Math.max(0, Math.round(getFrameAtOffset(x - 240, timelineZoom)) - 1); + console.log(frame); + api.start({ frame }); + }, { domTarget: ref, eventOptions: { passive: false } }); + + return +
+ {props.slide.type == 'loop' + ? + : } +
+
; +} + +function TimelineEditor(props: { + player: TimedVideoPlayer; +}) { + var timelineZoom = getTimelineZoom((st: any) => st.zoom); var timelineLabels = useTimelineLabels((st: any) => st.labels); var setTimelineLabels = useTimelineLabels((st: any) => st.setLabels); @@ -233,7 +235,7 @@ function TimelineEditor(props: {
kf.html)} + children={props.player?.timeline?.slides.map(slide => )} />
; diff --git a/styles/editor.css b/styles/editor.css index 5325004..3c30d68 100644 --- a/styles/editor.css +++ b/styles/editor.css @@ -218,7 +218,8 @@ overflow: visible; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3)); z-index: 1; - left: calc((var(--zoom) * (var(--frame) + 0.5)) * 1px - 1px) + left: calc((var(--zoom) * (var(--frame) + 0.5)) * 1px - 1px); + pointer-events: none; } .timeline .frameOverlay { @@ -228,9 +229,10 @@ opacity: .0; } - -.timeline .scrubberJumpArea { cursor: grab; } -.timeline .scrubberJumpArea:active { cursor: grabbing; } +.timeline .scrubberJumpArea, +.timeline .keyframes .frame .keyframeWrapper { cursor: grab; } +.timeline .scrubberJumpArea:active, +.timeline .keyframes .frame .keyframeWrapper:active { cursor: grabbing; } .timeline .scrubber .head { fill: var(--blue); } .timeline .scrubber .needle { background-color: var(--blue); } diff --git a/timeline.schema.json b/timeline.schema.json index c92e722..2d8c6ff 100644 --- a/timeline.schema.json +++ b/timeline.schema.json @@ -18,6 +18,9 @@ "frame": { "type": "number" }, + "id": { + "type": "string" + }, "type": { "$ref": "#/definitions/keyframeTypes" } @@ -26,6 +29,7 @@ "clickThroughBehaviour", "delay", "frame", + "id", "type" ], "type": "object" @@ -55,6 +59,9 @@ "frame": { "type": "number" }, + "id": { + "type": "string" + }, "playbackType": { "enum": [ "PingPong", @@ -70,6 +77,7 @@ "beginFrame", "clickThroughBehaviour", "frame", + "id", "playbackType", "type" ], @@ -101,6 +109,9 @@ "frame": { "type": "number" }, + "id": { + "type": "string" + }, "type": { "$ref": "#/definitions/keyframeTypes" } @@ -108,7 +119,8 @@ "required": [ "frame", "clickThroughBehaviour", - "type" + "type", + "id" ], "type": "object" }, @@ -125,6 +137,9 @@ "frame": { "type": "number" }, + "id": { + "type": "string" + }, "newFramerate": { "type": "number" }, @@ -135,6 +150,7 @@ "required": [ "clickThroughBehaviour", "frame", + "id", "newFramerate", "type" ], diff --git a/timeline.ts b/timeline.ts index 3a51ed3..764bc7a 100644 --- a/timeline.ts +++ b/timeline.ts @@ -4,6 +4,7 @@ export interface slide { frame: number; clickThroughBehaviour: 'ImmediatelySkip' | 'PlayOut'; type: keyframeTypes; + id: string; } export interface delaySlide extends slide { -- cgit v1.2.3