Klebende Reiterleiste und Zurück-nach-oben

Bei 2500 Karten scrollt man sonst lange, bis die Reiter wieder auftauchen.
Die Leiste bleibt jetzt oben stehen, der Knopf unten rechts bringt einen
zurück.

Er animiert selbst statt mit behavior: 'smooth'. Das rechnet mit fester
Geschwindigkeit und bräuchte über 300.000 Pixel Seitenhöhe Minuten; hier
sind es immer 450 ms.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013XVnRop5c3or3B8xE2hpgZ
This commit is contained in:
team3
2026-09-08 14:49:14 +02:00
parent 9840230250
commit 4de5018409

View File

@@ -225,6 +225,32 @@ const tabs = computed(() => [
const rad = ref(null)
// Bei 2500 Karten kommt man sonst nicht mehr nach oben
const obenKnopf = ref(false)
function beimScrollen() {
obenKnopf.value = window.scrollY > 800
}
// Eigene Animation statt behavior: 'smooth'. Das rechnet mit fester
// Geschwindigkeit und bräuchte über 300.000 Pixel Seitenhöhe Minuten.
const OBEN_DAUER = 450
function nachOben() {
const start = window.scrollY
const beginn = performance.now()
function schritt(jetzt) {
const t = Math.min(1, (jetzt - beginn) / OBEN_DAUER)
// Sanft an- und auslaufend
const p = t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2
window.scrollTo(0, start * (1 - p))
if (t < 1) requestAnimationFrame(schritt)
}
requestAnimationFrame(schritt)
}
// Die movie_ids der geschauten Filme — die Detailansicht zeigt damit an,
// ob der Film schon lief
const gesehen = ref([])
@@ -476,10 +502,12 @@ onMounted(() => {
else if (nachricht.type === 'features') ladeWuensche()
})
window.addEventListener('keydown', tastatur)
window.addEventListener('scroll', beimScrollen, { passive: true })
})
onUnmounted(() => {
window.removeEventListener('keydown', tastatur)
window.removeEventListener('scroll', beimScrollen)
abbestellen?.()
})
</script>
@@ -594,6 +622,10 @@ onUnmounted(() => {
/>
</div>
<button v-if="obenKnopf" type="button" class="nach-oben" title="Nach oben" @click="nachOben">
↑
</button>
<MovieDetail
v-if="selected"
:movie="selected"
@@ -625,12 +657,39 @@ onUnmounted(() => {
}
.tabs {
position: sticky;
top: 0;
z-index: 10;
display: flex;
gap: 0.35rem;
margin-bottom: 1.25rem;
/* Der negative Rand deckt das Polster der Seite ab, sonst scrollen
Karten oberhalb der Leiste durchs Bild */
margin: -1.5rem -1.25rem 1.25rem;
padding: 0.7rem 1.25rem 0;
background: var(--bg);
border-bottom: 1px solid var(--line);
}
.nach-oben {
position: fixed;
right: calc(var(--sidebar) + 1.25rem);
bottom: 1.5rem;
z-index: 15;
width: 3rem;
height: 3rem;
color: #fff;
font-size: 1.35rem;
line-height: 1;
background: var(--accent);
border: 0;
border-radius: 50%;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6);
}
.nach-oben:hover {
filter: brightness(1.15);
}
.tabs button {
display: flex;
align-items: center;