diff --git a/frontend/src/components/Guide.vue b/frontend/src/components/Guide.vue index 43eb3a2..1dc8850 100644 --- a/frontend/src/components/Guide.vue +++ b/frontend/src/components/Guide.vue @@ -68,7 +68,8 @@ const aktiv = ref('') const lese = ref(null) let beobachter = null let ladeSeq = 0 -// Leseposition auf dem Server merken (geräteübergreifend), gebündelt alle 1,5 s +// Leseposition auf dem Server merken (geräteübergreifend), gebündelt alle 1,5 s; nicht während des Sprungs beim Laden +let ruhe = false, ruheTimer = null let merkTimer = null function merken(id) { clearTimeout(merkTimer) @@ -88,6 +89,10 @@ async function laden() { spy() // Gemerkte Position hat Vorrang (die Adresse spiegelt nur den letzten Scrollstand); zuletzt im Lesemodus gelesen → dessen Stelle const ziel = idVonLesemodus(pos) || pos.abschnitt || idVonNr(props.nr) + // Der Sprung beim Laden darf die gemerkte Position nicht überschreiben; erst eigenes Scrollen zählt wieder + ruhe = true + clearTimeout(ruheTimer) + ruheTimer = setTimeout(() => { ruhe = false }, 2500) // Am Buchanfang (Vorwort) nicht scrollen, damit Titel und Knopfleiste sichtbar bleiben if (ziel && ziel !== 'vorwort' && !aktiv.value) scrollZu(ziel) } @@ -131,7 +136,7 @@ function spy() { beobachter?.disconnect() beobachter = new IntersectionObserver((es) => { if (lesemodus.value) return - for (const e of es) if (e.isIntersecting) { aktiv.value = e.target.id; merken(e.target.id); emit('nr', { nr: nrVonId(e.target.id), push: false }) } + for (const e of es) if (e.isIntersecting) { aktiv.value = e.target.id; if (!ruhe) merken(e.target.id); emit('nr', { nr: nrVonId(e.target.id), push: false }) } }, { root: lese.value, rootMargin: '0px 0px -75% 0px' }) document.querySelectorAll('.buch [data-spy]').forEach((el) => beobachter.observe(el)) }