Reduce performance lost on large screens
Some checks failed
Deploy with Docker Compose / deploy (push) Has been cancelled
Some checks failed
Deploy with Docker Compose / deploy (push) Has been cancelled
This commit is contained in:
@@ -23,49 +23,83 @@ const phrases = [
|
||||
"I like anime, all kinds of music and sci fic",
|
||||
];
|
||||
|
||||
// Non-reactive animation state to avoid triggering Vue re-renders every frame
|
||||
const animState = phrases.map((text, i) => ({
|
||||
x: i * 20,
|
||||
y: i * 20,
|
||||
dx: rand(0, 30) / 100,
|
||||
dy: 0.5,
|
||||
content: text,
|
||||
cachedW: 0,
|
||||
cachedH: 0,
|
||||
}));
|
||||
|
||||
// Reactive items only for initial render
|
||||
const items = ref<Item[]>(
|
||||
phrases.map((text, i) => ({
|
||||
x: i * 20,
|
||||
y: i * 20,
|
||||
dx: rand(0, 30) / 100,
|
||||
dy: 0.5,
|
||||
content: text,
|
||||
animState.map((s) => ({
|
||||
x: s.x,
|
||||
y: s.y,
|
||||
dx: s.dx,
|
||||
dy: s.dy,
|
||||
content: s.content,
|
||||
})),
|
||||
);
|
||||
|
||||
let rafId = 0;
|
||||
let cachedCW = 0;
|
||||
let cachedCH = 0;
|
||||
|
||||
function measureSizes() {
|
||||
const c = container.value;
|
||||
if (c) {
|
||||
cachedCW = c.clientWidth;
|
||||
cachedCH = c.clientHeight;
|
||||
}
|
||||
itemEls.value.forEach((el, i) => {
|
||||
if (el && animState[i]) {
|
||||
animState[i].cachedW = el.offsetWidth;
|
||||
animState[i].cachedH = el.offsetHeight;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function animate() {
|
||||
const c = container.value;
|
||||
if (!c) return;
|
||||
if (!cachedCW || !cachedCH) {
|
||||
rafId = requestAnimationFrame(animate);
|
||||
return;
|
||||
}
|
||||
|
||||
const cw = c.clientWidth;
|
||||
const ch = c.clientHeight;
|
||||
|
||||
items.value.forEach((item, i) => {
|
||||
for (let i = 0; i < animState.length; i++) {
|
||||
const s = animState[i];
|
||||
const el = itemEls.value[i];
|
||||
if (!el) return;
|
||||
if (!el) continue;
|
||||
|
||||
const ew = el.offsetWidth;
|
||||
const eh = el.offsetHeight;
|
||||
s.x += s.dx;
|
||||
s.y += s.dy;
|
||||
|
||||
item.x += item.dx;
|
||||
item.y += item.dy;
|
||||
if (s.x < 0 || s.x > cachedCW - s.cachedW) s.dx *= -1;
|
||||
if (s.y < 0 || s.y > cachedCH - s.cachedH) s.dy *= -1;
|
||||
|
||||
if (item.x < 0 || item.x > cw - ew) item.dx *= -1;
|
||||
if (item.y < 0 || item.y > ch - eh) item.dy *= -1;
|
||||
});
|
||||
el.style.transform = `translate(${s.x}px, ${s.y}px)`;
|
||||
}
|
||||
|
||||
rafId = requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
let resizeObserver: ResizeObserver;
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
measureSizes();
|
||||
rafId = requestAnimationFrame(animate);
|
||||
|
||||
resizeObserver = new ResizeObserver(measureSizes);
|
||||
resizeObserver.observe(container.value!);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
cancelAnimationFrame(rafId);
|
||||
resizeObserver?.disconnect();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -79,9 +113,6 @@ onUnmounted(() => {
|
||||
:key="i"
|
||||
ref="itemEls"
|
||||
class="absolute w-fit h-fit"
|
||||
:style="{
|
||||
transform: `translate(${item.x}px, ${item.y}px)`,
|
||||
}"
|
||||
>
|
||||
<h1>
|
||||
{{ item.content }}
|
||||
|
||||
Reference in New Issue
Block a user