fixed dogshit scroll

This commit is contained in:
2026-02-06 15:10:28 +00:00
parent 71d67272b1
commit 56ae7f3760

View File

@@ -1,50 +1,117 @@
<template>
<div ref="container" @mouseover="handleHover" class="overflow-y-auto">
<slot />
</div>
</template>
<script setup> <script setup>
import { useTemplateRef, onMounted, onBeforeUnmount } from "vue"; import { ref, onMounted, onBeforeUnmount, watchEffect } from "vue";
const container = useTemplateRef("container"); const container = ref(null);
const direction = ref(1); // 1 = down, -1 = up
const isPaused = ref(false);
const animationFrameId = ref(null);
const lastTime = ref(0);
const SPEED = 1; // px per frame const SPEED = 0.03; // px per ms (better for frame rate independence)
const PAUSE = 2000; // ms at top/bottom const PAUSE_DURATION = 2000; // ms at top/bottom
const FRAME_TIME = 50; // ms at top/bottom
let direction = 1; // 1 = down, -1 = up // Use requestAnimationFrame for smoother scrolling
let timeoutId; function scrollStep(timestamp) {
if (isPaused.value) return;
function handleHover() { if (!lastTime.value) lastTime.value = timestamp;
clearTimeout(timeoutId); const deltaTime = timestamp - lastTime.value;
timeoutId = setTimeout(tick, PAUSE); lastTime.value = timestamp;
}
if (!container.value) return;
function tick() {
const el = container.value; const el = container.value;
const scrollDistance = SPEED * deltaTime * direction.value;
el.scrollTop += SPEED * direction; el.scrollTop += scrollDistance;
const reachedBottom = el.scrollTop + el.clientHeight >= el.scrollHeight; const reachedBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 1;
const reachedTop = el.scrollTop <= 0; const reachedTop = el.scrollTop <= 1;
if (reachedBottom || reachedTop) { if (reachedBottom || reachedTop) {
direction *= -1; direction.value *= -1;
isPaused.value = true;
timeoutId = setTimeout(tick, PAUSE); setTimeout(() => {
isPaused.value = false;
if (!isPaused.value) {
animationFrameId.value = requestAnimationFrame(scrollStep);
}
}, PAUSE_DURATION);
return; return;
} }
timeoutId = setTimeout(tick, FRAME_TIME); animationFrameId.value = requestAnimationFrame(scrollStep);
}
function pauseScroll() {
isPaused.value = true;
lastTime.value = 0; // Reset time tracking
}
function resumeScroll() {
if (isPaused.value) {
isPaused.value = false;
animationFrameId.value = requestAnimationFrame(scrollStep);
}
}
function startScrolling() {
if (!isPaused.value) {
animationFrameId.value = requestAnimationFrame(scrollStep);
}
}
function stopScrolling() {
if (animationFrameId.value) {
cancelAnimationFrame(animationFrameId.value);
animationFrameId.value = null;
}
} }
onMounted(() => { onMounted(() => {
timeoutId = setTimeout(tick, FRAME_TIME); startScrolling();
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {
clearTimeout(timeoutId); stopScrolling();
});
// Optional: Auto-pause when component is not visible
const observer = ref(null);
onMounted(() => {
if ("IntersectionObserver" in window) {
observer.value = new IntersectionObserver(
(entries) => {
isPaused.value = !entries[0].isIntersecting;
if (!isPaused.value) {
startScrolling();
}
},
{ threshold: 0.1 },
);
if (container.value) {
observer.value.observe(container.value);
}
}
});
onBeforeUnmount(() => {
if (observer.value) {
observer.value.disconnect();
}
}); });
</script> </script>
<template>
<div
ref="container"
@mouseover="pauseScroll"
@mouseleave="resumeScroll"
class="overflow-y-auto"
>
<slot />
</div>
</template>