
Animazioni multi-layer e interazioni avanzate con GSAP: il caso Kineon
Il progetto Kineon è nato da un brief chiaro: un sito single-page ad alto impatto visivo per un'azienda competitiva nel settore dell'automazione industriale. Next.js 16, React 19, Tailwind CSS v4 e GSAP 3.15 sono stati gli strumenti. Nessun template, tutto custom su design di Alice Proglio. Le animazioni non dovevano essere decorative, ma funzionali: comunicare precisione e creare percezione di premium quality attraverso il movimento.
Parallasse 3D dell'Hero con tracking del mouse
L'hero presenta un braccio robotico statico. Il rischio? Sembrare piatto e privo di vita. La soluzione è stato un sistema multi-layer con tre profondità indipendenti, ognuna con velocità e timing diversi, animate con gsap.quickTo per massima fluidità senza jank.
Il glow spotlight (layer 1) segue il cursore con duration 1.2s e ease power2.out, simulando una sorgente luminosa che si muove con l'utente. Il braccio robotico (layer 2) combina traslazione X/Y a duration 0.6s con rotazione 3D (rotationX/Y) a duration 0.7s e transformPerspective 600. Questa dissociazione tra timing di traslazione e rotazione è deliberata: crea un'inerzia percepita che rende il movimento più organico e meno meccanico.
Il terzo layer (testo e contenuto) si muove nella direzione opposta al cursore: quando sposti il mouse a destra, il testo si muove a sinistra. Questo dettaglio è cruciale. Il movimento contrario amplifica la percezione di profondità: il testo appare come un layer "più lontano" rispetto al braccio, senza ricorrere a CSS 3D esplicito che rallenterebbe il rendering.
const handleMouseMove = (e: MouseEvent) => {
const x = e.clientX - window.innerWidth / 2;
const y = e.clientY - window.innerHeight / 2;
glowRef.current && gsap.quickTo(glowRef.current, { x: x * 0.3, y: y * 0.3 }, { duration: 1.2, ease: "power2.out" })();
armRef.current && gsap.quickTo(armRef.current, { x: x * 0.15, y: y * 0.15, rotationX: y * 0.05, rotationY: x * 0.05 }, { duration: 0.6 })();
textRef.current && gsap.quickTo(textRef.current, { x: -x * 0.1, y: -y * 0.1 }, { duration: 0.9 })();
};
const handleMouseLeave = () => {
gsap.to([glowRef.current, armRef.current, textRef.current], { x: 0, y: 0, rotationX: 0, rotationY: 0, duration: 0.8, ease: "power2.inOut" });
};
Pill tab switcher: quando il UI diventa oggetto
La sezione prodotti ha un tab switcher Machines / Robots. L'approccio CSS tradizionale (background che appare/scompare) è abrupato e visivamente statico. La soluzione è stata una pill assolutamente posizionata che scorre fisicamente da una tab all'altra, creando la percezione di un oggetto unico che si sposta.
Implementazione: getBoundingClientRect() su tab trigger e container list per calcolare la posizione relativa della pill. La pill parte da left:0 width:0, viene posizionata al mount con gsap.set() istantaneo (senza animazione) per evitare un "volo" iniziale. Al cambio tab, gsap.to() con ease back.out(1) e duration 0.55s. L'ease back.out aggiunge un leggero overshooting: la pill "atterra" con inerzia, come un oggetto fisico.
const handleTabChange = (value: string) => {
const trigger = document.querySelector(`[data-tab-trigger="${value}"]`);
const list = containerRef.current;
if (!trigger || !list) return;
const triggerRect = trigger.getBoundingClientRect();
const listRect = list.getBoundingClientRect();
const x = triggerRect.left - listRect.left;
gsap.to(pillRef.current, {
x,
width: triggerRect.width,
duration: 0.55,
ease: "back.out(1)"
});
setActiveTab(value);
};
// Nel JSX, la tab attiva ha data-[state=active]:bg-transparent
// per rimuovere il background nativo e evitare due sfondi sovrapposti.Dropdown mobile: timing sincronizzato e z-index discipline
Il menu mobile è stato riprogettato come tendina full-screen che scende dall'header. GSAP anima height da 0 a window.innerHeight - navbarHeight. Il valore target è calcolato runtime per gestire correttamente breakpoint diversi (navbar h-16 su mobile, h-24 su md).
Due dettagli critici: primo, il backdrop-blur dell'header si estende sulla tendina perché un div absolute inset-0 sul parent fixed copre tutto, quindi non serve duplicarlo. Secondo, un div relative z-10 sul dropdown garantisce che i link stiano sopra il layer blur — bug risolto: gli elementi absolute si dipingono sopra i figli in-flow nello stesso stacking context senza z-index esplicito.
Kineon è diventato un case study su come GSAP non sia uno strumento "per fare animazioni belle", ma un framework preciso di timing, easing e tracking del movimento. Ogni animazione risolve un problema specifico di UX: profondità percepita sull'hero, feedback visivo sul tab switcher, transizioni fluide sul mobile. Il risultato è un sito che comunica tecnologia e affidabilità non solo con il contenuto, ma con il modo in cui il contenuto si muove.


