feat: animazioni stile template prowess (reveal, parallax, marquee, hero, hover)

This commit is contained in:
2026-07-02 13:08:09 +02:00
parent e54daa105f
commit 0d9b645636
15 changed files with 129 additions and 34 deletions
+35
View File
@@ -25,10 +25,45 @@ const { title, description = 'InsanityLab — Performance. Balance. Longevity. A
<meta property="og:image" content={new URL('/img/og.jpg', Astro.site)} />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<link rel="sitemap" href="/sitemap-index.xml" />
<script is:inline>document.documentElement.classList.add('js');</script>
</head>
<body>
<Header />
<main><slot /></main>
<Footer />
<script>
// Reveal allo scroll: trigger a -100px dal viewport come il template Prowess.
const io = new IntersectionObserver((entries) => {
for (const e of entries) {
if (e.isIntersecting) {
e.target.classList.add('is-inview');
io.unobserve(e.target);
// A reveal concluso l'attributo va tolto, così la transition del reveal
// non rallenta gli hover su transform del componente.
e.target.addEventListener('transitionend', () => {
e.target.removeAttribute('data-reveal');
}, { once: true });
}
}
}, { rootMargin: '0px 0px -100px 0px' });
document.querySelectorAll('[data-reveal], .section-heading').forEach((el) => io.observe(el));
const parallaxEls = document.querySelectorAll<HTMLElement>('[data-parallax]');
if (parallaxEls.length && matchMedia('(min-width: 992px)').matches
&& !matchMedia('(prefers-reduced-motion: reduce)').matches) {
let raf = 0;
const update = () => {
raf = 0;
for (const el of parallaxEls) {
const r = el.getBoundingClientRect();
// Clamp entro il margine di sfondo (inset -120px) per non scoprire i bordi
const y = Math.max(-110, Math.min(110, (r.top + r.height / 2 - innerHeight / 2) * -0.3));
el.style.setProperty('--parallax-y', `${y.toFixed(1)}px`);
}
};
addEventListener('scroll', () => { if (!raf) raf = requestAnimationFrame(update); }, { passive: true });
update();
}
</script>
</body>
</html>