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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user