From b65f4d75f41e16f3a4c8edee95a135f5333784f2 Mon Sep 17 00:00:00 2001 From: team3 Date: Thu, 1 Oct 2026 00:45:19 +0200 Subject: [PATCH] update --- frontend/src/components/ClipTrimmer.vue | 65 +++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/ClipTrimmer.vue b/frontend/src/components/ClipTrimmer.vue index 443ba95..995c12b 100644 --- a/frontend/src/components/ClipTrimmer.vue +++ b/frontend/src/components/ClipTrimmer.vue @@ -4,7 +4,7 @@ // Mitte schiebt man das ganze Fenster. Daneben zieht man den Strahl // selbst nach links und rechts. Zeiten in Sekunden relativ zur Marke: // 0 ist der Moment, an dem C gedrückt wurde. -import { computed, ref } from 'vue' +import { computed, onMounted, onUnmounted, ref } from 'vue' const props = defineProps({ // Stücke der Aufnahme: [{ von, bis }] relativ zur Marke @@ -83,9 +83,27 @@ function uhrzeit(t) { // ── Ziehen ──────────────────────────────────────────────────────────── let griff = null let ausgang = null +// Ob sich die Hand seit dem Anfassen bewegt hat — sonst war es ein Klick +let bewegt = false + +function zeitBei(clientX) { + const box = strahl.value.getBoundingClientRect() + return links.value + ((clientX - box.left) / box.width) * spanne.value +} + +// Das Fenster an eine Stelle setzen: sein Anfang liegt dort, es bleibt im Stück +function setzen(t) { + const g = stueckUm(t) + const d = Math.max(props.minDauer, Math.min(dauer.value, g.bis - g.von)) + const s = Math.max(g.von, Math.min(g.bis - d, t)) + vorher.value = Math.round(-s) + dauer.value = Math.round(d) + emit('ende') +} function anfassen(e, was) { griff = was + bewegt = false ausgang = { x: e.clientX, vorher: vorher.value, @@ -100,6 +118,7 @@ function anfassen(e, was) { function ziehen(e) { if (!griff || !strahl.value) return const dt = ((e.clientX - ausgang.x) / strahl.value.clientWidth) * spanne.value + if (Math.abs(e.clientX - ausgang.x) > 4) bewegt = true const g = ausgang.stueck if (griff === 'bahn') { // Den Strahl selbst schieben — die Zeiten laufen der Hand entgegen @@ -134,9 +153,46 @@ function loslassen(e) { const war = griff griff = null e.currentTarget.releasePointerCapture?.(e.pointerId) - // Nur ein verändertes Fenster braucht eine neue Vorschau - if (war !== 'bahn') emit('ende') + if (war === 'bahn') { + // Ein Klick ohne Ziehen setzt das Fenster hierhin; Schieben braucht keine neue Vorschau + if (!bewegt) setzen(zeitBei(e.clientX)) + return + } + emit('ende') } + +// Mausrad: zoomen, der Punkt unter dem Zeiger bleibt stehen +function rad(e) { + const neu = Math.max(0, Math.min(ZOOMS.length - 1, zoom.value + (e.deltaY > 0 ? 1 : -1))) + if (neu === zoom.value || !strahl.value) return + const box = strahl.value.getBoundingClientRect() + const anteil = (e.clientX - box.left) / box.width + const t = links.value + anteil * spanne.value + zoom.value = neu + const r = grenzen.value + mitte.value = Math.max(r.von, Math.min(r.bis, t - (anteil - 0.5) * ZOOMS[neu])) +} + +// Pfeiltasten: 1 s, mit Shift 10 s. Die Vorschau lädt erst, wenn Ruhe ist +let tastenTimer = null + +function taste(e) { + if (e.target instanceof Element && e.target.matches('input, textarea')) return + if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return + e.preventDefault() + const schritt = (e.shiftKey ? 10 : 1) * (e.key === 'ArrowLeft' ? -1 : 1) + const g = stueckUm(start.value + dauer.value / 2) + const s = Math.max(g.von, Math.min(g.bis - dauer.value, start.value + schritt)) + vorher.value = Math.round(-s) + clearTimeout(tastenTimer) + tastenTimer = setTimeout(() => emit('ende'), 400) +} + +onMounted(() => window.addEventListener('keydown', taste)) +onUnmounted(() => { + window.removeEventListener('keydown', taste) + clearTimeout(tastenTimer) +})