update
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
// Mitte schiebt man das ganze Fenster. Daneben zieht man den Strahl
|
// Mitte schiebt man das ganze Fenster. Daneben zieht man den Strahl
|
||||||
// selbst nach links und rechts. Zeiten in Sekunden relativ zur Marke:
|
// selbst nach links und rechts. Zeiten in Sekunden relativ zur Marke:
|
||||||
// 0 ist der Moment, an dem C gedrückt wurde.
|
// 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({
|
const props = defineProps({
|
||||||
// Stücke der Aufnahme: [{ von, bis }] relativ zur Marke
|
// Stücke der Aufnahme: [{ von, bis }] relativ zur Marke
|
||||||
@@ -83,9 +83,27 @@ function uhrzeit(t) {
|
|||||||
// ── Ziehen ────────────────────────────────────────────────────────────
|
// ── Ziehen ────────────────────────────────────────────────────────────
|
||||||
let griff = null
|
let griff = null
|
||||||
let ausgang = 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) {
|
function anfassen(e, was) {
|
||||||
griff = was
|
griff = was
|
||||||
|
bewegt = false
|
||||||
ausgang = {
|
ausgang = {
|
||||||
x: e.clientX,
|
x: e.clientX,
|
||||||
vorher: vorher.value,
|
vorher: vorher.value,
|
||||||
@@ -100,6 +118,7 @@ function anfassen(e, was) {
|
|||||||
function ziehen(e) {
|
function ziehen(e) {
|
||||||
if (!griff || !strahl.value) return
|
if (!griff || !strahl.value) return
|
||||||
const dt = ((e.clientX - ausgang.x) / strahl.value.clientWidth) * spanne.value
|
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
|
const g = ausgang.stueck
|
||||||
if (griff === 'bahn') {
|
if (griff === 'bahn') {
|
||||||
// Den Strahl selbst schieben — die Zeiten laufen der Hand entgegen
|
// Den Strahl selbst schieben — die Zeiten laufen der Hand entgegen
|
||||||
@@ -134,9 +153,46 @@ function loslassen(e) {
|
|||||||
const war = griff
|
const war = griff
|
||||||
griff = null
|
griff = null
|
||||||
e.currentTarget.releasePointerCapture?.(e.pointerId)
|
e.currentTarget.releasePointerCapture?.(e.pointerId)
|
||||||
// Nur ein verändertes Fenster braucht eine neue Vorschau
|
if (war === 'bahn') {
|
||||||
if (war !== 'bahn') emit('ende')
|
// 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)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -162,6 +218,7 @@ function loslassen(e) {
|
|||||||
ref="strahl"
|
ref="strahl"
|
||||||
class="strahl"
|
class="strahl"
|
||||||
@pointerdown="anfassen($event, 'bahn')"
|
@pointerdown="anfassen($event, 'bahn')"
|
||||||
|
@wheel.prevent="rad"
|
||||||
@pointermove="ziehen"
|
@pointermove="ziehen"
|
||||||
@pointerup="loslassen"
|
@pointerup="loslassen"
|
||||||
@pointercancel="loslassen"
|
@pointercancel="loslassen"
|
||||||
@@ -257,6 +314,8 @@ function loslassen(e) {
|
|||||||
.bereich {
|
.bereich {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0.4rem;
|
top: 0.4rem;
|
||||||
|
/* Bei vier Stunden Ansicht wäre das Fenster ein Strich — so bleibt es greifbar */
|
||||||
|
min-width: 2.2rem;
|
||||||
height: 1.6rem;
|
height: 1.6rem;
|
||||||
background: rgba(229, 9, 20, 0.35);
|
background: rgba(229, 9, 20, 0.35);
|
||||||
border: 2px solid var(--accent);
|
border: 2px solid var(--accent);
|
||||||
|
|||||||
Reference in New Issue
Block a user