import { CSSProperties, ReactNode, useEffect, useState } from 'react'; import create from 'zustand'; import { loopSlide } from '../timeline'; import { TimedVideoPlayer } from './present'; import AppBar from '@material-ui/core/AppBar'; import Button from '@material-ui/core/Button'; import ButtonGroup from '@material-ui/core/ButtonGroup'; import Fab from '@material-ui/core/Fab'; import Slider from '@material-ui/core/Slider'; import Toolbar from '@material-ui/core/Toolbar'; import ZoomInRoundedIcon from '@material-ui/icons/ZoomInRounded'; import ZoomOutRoundedIcon from '@material-ui/icons/ZoomOutRounded'; import Icon from '@mdi/react'; import { PressureIcon, SlideKeyframe } from '../components/icons'; import Loop from '../components/loop'; import FullscreenRoundedIcon from '@material-ui/icons/FullscreenRounded'; import NavigateBeforeRoundedIcon from '@material-ui/icons/NavigateBeforeRounded'; import NavigateNextRoundedIcon from '@material-ui/icons/NavigateNextRounded'; import PauseRoundedIcon from '@material-ui/icons/PauseRounded'; import SkipPreviousRoundedIcon from '@material-ui/icons/SkipPreviousRounded'; import { mdiCursorDefault } from '@mdi/js'; var getTimelineZoom = create(set => ({ zoom: 0.2, changeZoom: (delta: number) => set((st: any) => ({ zoom: Math.min(1, Math.max(0, st.zoom + delta)) })), setZoom: (newValue: number) => set(() => ({ zoom: newValue })), })); var useTimelineLabels = create(set => ({ labels: [], setLabels: (newLabels: Array) => set(() => ({ labels: newLabels })), })); var useFrame = create(set => ({ currentFrame: 0, setFrame: (newFrame: number) => set(() => ({ currentFrame: newFrame })), })); function TimelineEditor(props: { player: TimedVideoPlayer; }) { var keyframes = props.player?.timeline?.slides.map(slide =>
{slide.type == 'loop' ? : }
); var timelineLabels = useTimelineLabels((st: any) => st.labels); var setTimelineLabels = useTimelineLabels((st: any) => st.setLabels); var frame = useFrame((st: any) => st.currentFrame); var setFrame = useFrame((st: any) => st.setFrame); 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; */ /* }); */ function onframe(frame: number) { setFrame(frame); } props.player.onframe = onframe; var css = (varname: string) => getComputedStyle(document.body).getPropertyValue(varname).trim(); var baseColor = css('--c100'); var frameColor = css('--c250'); var markerFrame = css('--c400'); function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); var labels: Array = []; var offset = document.querySelector('.timeline .timelineInner').scrollLeft; var frameWidth = Number( getComputedStyle(document.querySelector('.timeline')).getPropertyValue('--zoom').trim(), ); var d = true; var a = 1; var ns = [300, 150, 120, 90, 60, 30, 30, 30, 15, 15, 10, 10, 10]; var everyN = ns[Math.floor(frameWidth)]; for (var x = -offset; x < canvas.width + offset; x += frameWidth) { ctx.fillStyle = baseColor; var rect = [Math.round(x + (frameWidth - 2) / 2), 28, 2, canvas.height]; var drawFrame = false; var marker = false; if (frameWidth >= 6) { ctx.fillStyle = d ? baseColor : frameColor; rect = [x, 28, frameWidth, canvas.height]; drawFrame = !d; } /* if (a * 2 % everyN == 0) { */ /* ctx.fillStyle = frameColor; */ /* drawFrame = true; */ /* } */ if (a % everyN == 0) { ctx.fillStyle = markerFrame; drawFrame = true; marker = true; } if (drawFrame) { ctx.fillRect(rect[0], rect[1], rect[2], rect[3]); if (marker) { var frame = Math.round(x / frameWidth + offset / frameWidth + 1); labels.push( , ); } } d = !d; a++; } setTimelineLabels(labels); 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 <>
{timelineLabels}
{keyframes}
; } export default function Index() { var [dummy, setDummy] = useState(false); var rerender = () => setDummy(!dummy); var [player, setPlayer] = useState(new TimedVideoPlayer()); var timelineZoom = getTimelineZoom((st: any) => st.zoom); var setTimelineZoom = getTimelineZoom((st: any) => st.setZoom); var frame = useFrame((st: any) => st.currentFrame); useEffect(() => { var videoEL = document.getElementById('player') as HTMLVideoElement; player.registerPlayer(videoEL); }, []); var changeZoom = getTimelineZoom(st => (st as any).changeZoom); useEffect(() => { document.querySelector('.timeline').addEventListener('wheel', (e: WheelEvent) => { if (!e.ctrlKey && !e.altKey) return; e.preventDefault(); changeZoom(-e.deltaY / 1000); }, { passive: false }); }, []); return <>

pressure

{ var file = event.target.files[0]; if (!file) return; var reader = new FileReader(); reader.addEventListener('load', ev => { player.loadVideo(ev.target.result as string); }); reader.readAsDataURL(file); }} /> { var file = event.target.files[0]; if (!file) return; var reader = new FileReader(); reader.addEventListener('load', ev => { player.loadSlides(ev.target.result as string); rerender(); }); reader.readAsText(file); }} />
} /> } onClick={() => player.next()} /> } onClick={() => player.previous()} /> } />
} />
@{player.framerate}fps

{player.frameToTimestampString(frame, false)}

{ setTimelineZoom(newValue as number); }} min={0} step={0.00000001} max={1} aria-labelledby='continuous-slider' />
; }