From 9604fdf8302a1510840470004dc315b63a7522ea Mon Sep 17 00:00:00 2001 From: lonkaars Date: Sun, 16 May 2021 19:51:17 +0200 Subject: timeline divisions --- pages/editor.tsx | 106 +++++++++++++++++++++++++++++++++++++----------------- readme.md | 5 +++ styles/editor.css | 20 +++++------ 3 files changed, 87 insertions(+), 44 deletions(-) diff --git a/pages/editor.tsx b/pages/editor.tsx index 01cd989..36a4c66 100644 --- a/pages/editor.tsx +++ b/pages/editor.tsx @@ -25,44 +25,86 @@ import { mdiCursorDefault } from '@mdi/js'; function TimelineEditor(props: { player: TimedVideoPlayer; }) { - var frames = [...new Array(props.player.timeline?.framecount || 0)].map((el, i) => -
-
- - {props.player?.frameToTimestampString(i + 1)} - + var keyframes = props.player?.timeline?.slides.map(slide => +
- {(() => { - var slide = props.player?.timeline?.slides.find(slide => slide.frame == i + 1); - if (slide) { - if (slide.type == 'loop') { - return ; - } else { - return ; - } - } - })()} + {slide.type == 'loop' + ? + : }
); + useEffect(() => { + var canvas = document.getElementById('timeScaleCanvas') as HTMLCanvasElement; + var ctx = canvas.getContext('2d'); + + var mouseX = 0; + var mouseY = 0; + + window.addEventListener('mousemove', e => { + var rect = canvas.getBoundingClientRect(); + mouseX = e.clientX - rect.x; + mouseY = e.clientY - rect.y; + }); + + var css = (varname: string) => getComputedStyle(document.body).getPropertyValue(varname).trim(); + var textColor = css('--c100'); + var lineColor = css('--c300'); + + function draw() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + + var offset = document.querySelector('.timeline .timelineInner').scrollLeft; + + var d = true; + var frameWidth = Number( + getComputedStyle(document.querySelector('.timeline')).getPropertyValue('--zoom').trim(), + ); + var a = 1; + var ns = [300, 150, 120, 90, 60, 30, 30, 30, 15, 15, 15, 15, 15]; + var everyN = ns[Math.floor(frameWidth)]; + for (var x = -offset; x < canvas.width + offset; x += frameWidth) { + ctx.fillStyle = d ? textColor : lineColor; + if (a % everyN == 0) ctx.fillStyle = '#ff00ff'; + ctx.fillRect(x, 0, frameWidth, canvas.height); + d = !d; + a++; + } + + requestAnimationFrame(draw); + } + draw(); + + function onresize() { + var size = document.querySelector('.timeline .timelineInner .keyframes'); + canvas.width = size.clientWidth; + canvas.height = size.clientHeight; + } + onresize(); + window.addEventListener('resize', onresize); + }, []); + return <> -
- - - -
-
+ +
+
+ + + +
+
+
+
{keyframes}
-
{frames}
; } @@ -71,7 +113,7 @@ export default function Index() { var rerender = () => setDummy(!dummy); var [player, setPlayer] = useState(new TimedVideoPlayer()); - var [timelineZoom, setTimelineZoom] = useState(4); + var [timelineZoom, setTimelineZoom] = useState(0.2); useEffect(() => { var videoEL = document.getElementById('player') as HTMLVideoElement; diff --git a/readme.md b/readme.md index ab6f2f5..2f1ba92 100644 --- a/readme.md +++ b/readme.md @@ -28,6 +28,11 @@ when I'm working on them/are finished: timeline.json file. Maybe also a feature where you could import recorded presentation timings for adding a voice-over and re-exporting the video as a standalone video. +- **Manim add-on library** + Would allow adding of something like `pressure.slide()` or + `pressure.slide('speedChange', 0.7)` to your Manim scene source and export it + using a simple python cli script, or alongside the regular Manim renderer if + that's possible. ## designs diff --git a/styles/editor.css b/styles/editor.css index 9e315ca..4b1e006 100644 --- a/styles/editor.css +++ b/styles/editor.css @@ -156,36 +156,32 @@ margin: 4px; } -.appGrid .timeline { - --zoom: 4; -} - -.appGrid .timeline .frames { +.appGrid .timeline .keyframes { height: 100%; } -.appGrid .timeline .frames .frame { +.appGrid .timeline .keyframes .frame { background-color: transparent; height: 100%; width: calc(var(--zoom) * 1px); display: inline-block; border-radius: 2px 2px 0 0; - position: relative; overflow: visible; + left: calc(var(--zoom) * (var(--frame) - 1) * 1px); } -.appGrid .timeline .frames .frame:nth-child(30n) .line { +.appGrid .timeline .keyframes .frame:nth-child(30n) .line { background-color: var(--c300); top: 28px; width: 2px; border-radius: 2px 2px 0 0; } -.appGrid .timeline .frames .frame .timecode { +.appGrid .timeline .keyframes .frame .timecode { display: none; } -.appGrid .timeline .frames .frame .keyframeWrapper { +.appGrid .timeline .keyframes .frame .keyframeWrapper { line-height: 0; top: 44px; z-index: 999; @@ -194,7 +190,7 @@ height: 24px; } -.appGrid .timeline .frames .frame:nth-child(30n) .timecode { +.appGrid .timeline .keyframes .frame:nth-child(30n) .timecode { color: var(--c700); font-weight: 500; line-height: 1; @@ -202,7 +198,7 @@ top: 12px; } -.appGrid .timeline { +.appGrid .timeline .timelineInner { overflow-y: hidden; overflow-x: scroll; white-space: nowrap; -- cgit v1.2.3