bak
This commit is contained in:
1 parent
e851d52aef
commit
fcefd258eb
6 files changed
+533
-91
No files matched your search
+126
-5
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import {
|
||||
PhArrowClockwise,
|
||||
PhArrowCounterClockwise,
|
||||
@@ -47,6 +47,78 @@ const exportOpen = ref(false)
|
||||
const testsOpen = ref(false)
|
||||
const welcomeOpen = ref(false)
|
||||
const fullscreenOpen = ref(false)
|
||||
const TIMELINE_HEIGHT_KEY = 'animatr:timelineHeight'
|
||||
const DEFAULT_TIMELINE_HEIGHT = 220
|
||||
const MIN_TIMELINE_HEIGHT = 120
|
||||
const MAX_TIMELINE_HEIGHT_MARGIN = 160
|
||||
|
||||
function readStoredTimelineHeight(): number {
|
||||
try {
|
||||
const raw = localStorage.getItem(TIMELINE_HEIGHT_KEY)
|
||||
if (raw === null) return DEFAULT_TIMELINE_HEIGHT
|
||||
const n = Number.parseInt(raw, 10)
|
||||
if (Number.isFinite(n) && n >= MIN_TIMELINE_HEIGHT) return n
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
return DEFAULT_TIMELINE_HEIGHT
|
||||
}
|
||||
|
||||
const timelineHeight = ref(readStoredTimelineHeight())
|
||||
|
||||
function maxTimelineHeight(): number {
|
||||
return Math.max(MIN_TIMELINE_HEIGHT, window.innerHeight - MAX_TIMELINE_HEIGHT_MARGIN)
|
||||
}
|
||||
|
||||
const appStyle = computed(() => ({
|
||||
'--timeline-height': `${timelineHeight.value}px`,
|
||||
}))
|
||||
|
||||
let resizeStartY = 0
|
||||
let resizeStartHeight = 0
|
||||
let resizePointerId = -1
|
||||
const resizing = ref(false)
|
||||
|
||||
function onTimelineResizeStart(e: PointerEvent) {
|
||||
if (e.button !== 0) return
|
||||
e.preventDefault()
|
||||
const el = e.currentTarget as HTMLElement
|
||||
el.setPointerCapture(e.pointerId)
|
||||
resizePointerId = e.pointerId
|
||||
resizeStartY = e.clientY
|
||||
resizeStartHeight = timelineHeight.value
|
||||
resizing.value = true
|
||||
document.body.style.userSelect = 'none'
|
||||
}
|
||||
|
||||
function onTimelineResizeMove(e: PointerEvent) {
|
||||
if (!resizing.value || e.pointerId !== resizePointerId) return
|
||||
const dy = resizeStartY - e.clientY
|
||||
const next = Math.max(
|
||||
MIN_TIMELINE_HEIGHT,
|
||||
Math.min(maxTimelineHeight(), resizeStartHeight + dy),
|
||||
)
|
||||
timelineHeight.value = next
|
||||
}
|
||||
|
||||
function onTimelineResizeEnd(e: PointerEvent) {
|
||||
if (!resizing.value || e.pointerId !== resizePointerId) return
|
||||
const el = e.currentTarget as HTMLElement
|
||||
if (el.hasPointerCapture(e.pointerId)) el.releasePointerCapture(e.pointerId)
|
||||
resizePointerId = -1
|
||||
resizing.value = false
|
||||
document.body.style.userSelect = ''
|
||||
try {
|
||||
localStorage.setItem(TIMELINE_HEIGHT_KEY, String(timelineHeight.value))
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
const max = maxTimelineHeight()
|
||||
if (timelineHeight.value > max) timelineHeight.value = max
|
||||
}
|
||||
const loadError = ref<string | null>(null)
|
||||
const savedToast = ref<string | null>(null)
|
||||
const currentProjectId = ref<string | null>(null)
|
||||
@@ -189,13 +261,17 @@ function onKeyDown(e: KeyboardEvent) {
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('keydown', onKeyDown)
|
||||
window.addEventListener('resize', onWindowResize)
|
||||
bootWelcome()
|
||||
})
|
||||
onBeforeUnmount(() => document.removeEventListener('keydown', onKeyDown))
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener('keydown', onKeyDown)
|
||||
window.removeEventListener('resize', onWindowResize)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app">
|
||||
<div class="app" :style="appStyle">
|
||||
<header class="topbar">
|
||||
<div class="brand-area">
|
||||
<span class="brand">
|
||||
@@ -279,7 +355,18 @@ onBeforeUnmount(() => document.removeEventListener('keydown', onKeyDown))
|
||||
</aside>
|
||||
<main class="stage"><CanvasStage /></main>
|
||||
<aside class="properties"><PropertiesPanel /></aside>
|
||||
<footer class="timeline"><Timeline /></footer>
|
||||
<footer class="timeline">
|
||||
<div
|
||||
class="tl-resize"
|
||||
:class="{ resizing }"
|
||||
title="Timeline-Höhe ziehen"
|
||||
@pointerdown="onTimelineResizeStart"
|
||||
@pointermove="onTimelineResizeMove"
|
||||
@pointerup="onTimelineResizeEnd"
|
||||
@pointercancel="onTimelineResizeEnd"
|
||||
></div>
|
||||
<Timeline />
|
||||
</footer>
|
||||
<DocumentSettings v-model="settingsOpen" />
|
||||
<ExportDialog v-model="exportOpen" />
|
||||
<TestOverlay v-model="testsOpen" />
|
||||
@@ -303,7 +390,7 @@ onBeforeUnmount(() => document.removeEventListener('keydown', onKeyDown))
|
||||
.app {
|
||||
display: grid;
|
||||
grid-template-columns: 260px 1fr 300px;
|
||||
grid-template-rows: 48px 1fr 220px;
|
||||
grid-template-rows: 48px 1fr var(--timeline-height, 220px);
|
||||
grid-template-areas:
|
||||
'top top top'
|
||||
'side stage props'
|
||||
@@ -480,6 +567,40 @@ onBeforeUnmount(() => document.removeEventListener('keydown', onKeyDown))
|
||||
background: var(--panel);
|
||||
border-top: 1px solid var(--border);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tl-resize {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 14px;
|
||||
cursor: ns-resize;
|
||||
z-index: 20;
|
||||
touch-action: none;
|
||||
background: transparent;
|
||||
transition: background 120ms var(--ease);
|
||||
}
|
||||
|
||||
.tl-resize::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 7px;
|
||||
height: 1px;
|
||||
background: transparent;
|
||||
transition: background 120ms var(--ease);
|
||||
}
|
||||
|
||||
.tl-resize:hover::after,
|
||||
.tl-resize.resizing::after {
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.tl-resize.resizing {
|
||||
background: rgba(110, 168, 255, 0.08);
|
||||
}
|
||||
|
||||
.project-name {
|
||||
|
||||
Reference in new issue
Block a user