fixed justify and improved sigils
This commit is contained in:
@@ -23,11 +23,16 @@
|
||||
<script>
|
||||
import { buildCybersigil } from '../lib/cybersigil';
|
||||
|
||||
let teardown: (() => void) | null = null;
|
||||
|
||||
function initCyberFx() {
|
||||
const root = document.documentElement;
|
||||
if (!root.classList.contains('cybersigil')) return;
|
||||
const fx = document.querySelector<HTMLElement>('.cs-fx');
|
||||
if (!fx) return;
|
||||
|
||||
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
const fine = window.matchMedia('(pointer: fine)').matches;
|
||||
|
||||
/* ─── Generated sigil growths in the four corners ─── */
|
||||
/* One sigil per page load; the four corner transforms in global.css
|
||||
@@ -42,10 +47,11 @@
|
||||
});
|
||||
}
|
||||
|
||||
/* ─── One slow-spinning sigil filling the background ─── */
|
||||
/* ─── One sigil filling the background. count:6 (was 9) — fewer branch
|
||||
* nodes ⇒ far fewer perpetually-animating strokes, same silhouette. ─── */
|
||||
const wire = document.querySelector<HTMLElement>('.cs-fx-wire');
|
||||
if (wire && !wire.classList.contains('cs-fx-wire--sig')) {
|
||||
wire.innerHTML = buildCybersigil({ count: 9 });
|
||||
wire.innerHTML = buildCybersigil({ count: 6 });
|
||||
wire.classList.add('cs-fx-wire--sig');
|
||||
}
|
||||
|
||||
@@ -72,6 +78,60 @@
|
||||
targets.forEach((t) => io.observe(t));
|
||||
}
|
||||
}
|
||||
|
||||
/* ─── Ambient: entrance fade-in (opacity:0 → target via the CSS
|
||||
* transition on first apply), scroll-depth recede, scroll + pointer
|
||||
* parallax. Parallax is gated on fine pointers and reduced-motion;
|
||||
* the depth fade is just opacity tied to scroll position. ─── */
|
||||
if (teardown) teardown();
|
||||
const off: Array<() => void> = [];
|
||||
let depth = 0, px = 0, py = 0, raf = 0;
|
||||
|
||||
const apply = () => {
|
||||
raf = 0;
|
||||
fx.style.opacity = String(1 - 0.5 * depth);
|
||||
if (!reduced) {
|
||||
fx.style.setProperty('--cs-px', px.toFixed(1) + 'px');
|
||||
fx.style.setProperty('--cs-py', (py + depth * 24).toFixed(1) + 'px');
|
||||
fx.style.setProperty('--cs-cx', (-px * 0.42).toFixed(1) + 'px');
|
||||
fx.style.setProperty('--cs-cy', (-py * 0.42).toFixed(1) + 'px');
|
||||
}
|
||||
};
|
||||
const schedule = () => { if (!raf) raf = requestAnimationFrame(apply); };
|
||||
|
||||
const onScroll = () => {
|
||||
const vh = window.innerHeight || 1;
|
||||
depth = Math.max(0, Math.min(1, window.scrollY / vh));
|
||||
schedule();
|
||||
};
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
window.addEventListener('resize', onScroll);
|
||||
off.push(() => window.removeEventListener('scroll', onScroll));
|
||||
off.push(() => window.removeEventListener('resize', onScroll));
|
||||
onScroll();
|
||||
|
||||
if (!reduced && fine) {
|
||||
const onPointer = (e: PointerEvent | MouseEvent) => {
|
||||
const w = window.innerWidth || 1, h = window.innerHeight || 1;
|
||||
px = (e.clientX / w - 0.5) * 26; // ≈ ±13px drift
|
||||
py = (e.clientY / h - 0.5) * 26;
|
||||
schedule();
|
||||
};
|
||||
window.addEventListener('pointermove', onPointer, { passive: true });
|
||||
off.push(() => window.removeEventListener('pointermove', onPointer));
|
||||
}
|
||||
|
||||
/* Freeze every loop while the tab is hidden — idle-battery win. */
|
||||
const onVis = () => fx.classList.toggle('is-paused', document.hidden);
|
||||
document.addEventListener('visibilitychange', onVis);
|
||||
off.push(() => document.removeEventListener('visibilitychange', onVis));
|
||||
onVis();
|
||||
|
||||
teardown = () => {
|
||||
if (raf) cancelAnimationFrame(raf);
|
||||
off.forEach((fn) => fn());
|
||||
teardown = null;
|
||||
};
|
||||
}
|
||||
|
||||
initCyberFx();
|
||||
|
||||
Reference in New Issue
Block a user