Arquiteto de Sistemas de Animação
Crie sistemas de animação performáticos e acessíveis usando Framer Motion, GSAP, a View Transitions API e física de molas para experiências de UI fluidas.
Gatilhos de Ativação
Ativar em: transições de página, animações de layout, animações acionadas por rolagem, micro-interações, física de molas, motion.div, gsap.to, View Transition API, transições de elemento compartilhado, animações de lista em cascata.
NÃO para: efeitos hover/focus apenas com CSS — use css-in-js-architect. Renderização Canvas/WebGL — use creative-coding-expert. Reprodução de arquivos Lottie — use integração Lottie padrão.
Início Rápido
- Escolha seu mecanismo — Framer Motion para React declarativo, GSAP para animações baseadas em timeline ou projetos não-React, View Transitions API para navegação entre páginas.
- Anime apenas transformações e opacidade — estas são executadas no thread do compositor (GPU), evitando oscilações de layout.
- Use
will-changecom moderação — apenas em elementos prestes a animar, remova após a conclusão. - Respeite
prefers-reduced-motion— desabilite ou simplifique todas as animações para usuários que o solicitarem. - Perfile com DevTools — guia Performance > verifique se há mudanças de layout durante as animações.
Capacidades Principais
| Domínio | Tecnologias | Padrões Chave |
|---|---|---|
| React Declarativo | Framer Motion 11+, componentes motion | Animações de layout, AnimatePresence, variantes |
| Animação em Timeline | GSAP 3.12+, ScrollTrigger | Sequências acionadas por rolagem, fixação, escrutínio |
| Transições de Página | View Transitions API, useViewTransition do Next.js | Transições de elemento compartilhado entre páginas |
| Física de Molas | Molas do Framer Motion, react-spring | Suavização natural, animações interrompíveis |
| Micro-interações | Transições CSS + Framer Motion | Feedback de botão, estados de hover, indicadores de carregamento |
| Acionado por Rolagem | animation-timeline: scroll() do CSS, GSAP ScrollTrigger | Paralaxe, indicadores de progresso, revelação ao rolar |
Padrões de Arquitetura
Padrão 1: Animações de Layout com Framer Motion
import { motion, AnimatePresence, LayoutGroup } from 'framer-motion';
function FilterableGrid({ items, filter }: Props) {
const filtered = items.filter(item => item.category === filter);
return (
<LayoutGroup>
<motion.div layout className="grid grid-cols-3 gap-4">
<AnimatePresence mode="popLayout">
{filtered.map(item => (
<motion.div
key={item.id}
layout // anima mudanças de posição
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ type: 'spring', stiffness: 300, damping: 25 }}
>
<Card item={item} />
</motion.div>
))}
</AnimatePresence>
</motion.div>
</LayoutGroup>
);
}
Padrão 2: View Transitions API para Navegação de Página
// app/components/TransitionLink.tsx
'use client';
import { useRouter } from 'next/navigation';
import { useCallback } from 'react';
export function TransitionLink({ href, children }: { href: string; children: React.ReactNode }) {
const router = useRouter();
const handleClick = useCallback((e: React.MouseEvent) => {
e.preventDefault();
if (!document.startViewTransition) {
router.push(href);
return;
}
document.startViewTransition(() => {
router.push(href);
});
}, [href, router]);
return <a href={href} onClick={handleClick}>{children}</a>;
}
/* Transições de elemento compartilhado via view-transition-name */
.product-image {
view-transition-name: product-hero;
}
::view-transition-old(product-hero) {
animation: fade-and-scale 0.3s ease-out;
}
::view-transition-new(product-hero) {
animation: fade-and-scale 0.3s ease-in reverse;
}
Padrão 3: Respeito ao Movimento Reduzido
import { useReducedMotion } from 'framer-motion';
function AnimatedComponent() {
const shouldReduce = useReducedMotion();
return (
<motion.div
initial={{ opacity: 0, y: shouldReduce ? 0 : 20 }}
animate={{ opacity: 1, y: 0 }}
transition={shouldReduce
? { duration: 0 }
: { type: 'spring', stiffness: 260, damping: 20 }
}
>
Content
</motion.div>
);
}
┌─ Árvore de Decisão de Animação ──────────────────┐
│ │
│ prefers-reduced-motion? │
│ ├── SIM → apenas fade de opacidade instantâneo │
│ └── NÃO → animação completa com mola/transform │
│ │
│ O que está sendo animado? │
│ ├── transform/opacity → GPU compositor (bom) │
│ ├── width/height → oscilação de layout (evitar) │
│ └── box-shadow → apenas pintura (aceitável) │
└───────────────────────────────────────────────────┘
Antipadrões
- Animar
width,height,top,left— dispara recálculo de layout a cada quadro. Usetransform: translate/scalepara alcançar 60fps. will-changeem todos os elementos — promove muitas camadas para a GPU, aumentando o uso de memória. Aplique apenas em elementos prestes a animar.- Ignorar
prefers-reduced-motion— usuários sensíveis a movimento podem sentir náuseas ou convulsões. Sempre verifique e respeite esta media query. - Duração da animação > 500ms para micro-interações — torna a UI lenta. Mantenha feedback de botão/hover abaixo de 200ms, transições de página abaixo de 400ms.
- Animar durante a rolagem sem
requestAnimationFrameou ScrollTrigger — causa gagueira. Use GSAP ScrollTrigger ouanimation-timeline: scroll()do CSS para animações acionadas por rolagem.
Lista de Verificação de Qualidade
- Todas as animações usam
transformeopacity(propriedades amigáveis ao compositor) -
prefers-reduced-motionrespeitado comuseReducedMotionou media query CSS - Micro-interações abaixo de 200ms, transições de página abaixo de 400ms
-
AnimatePresenceusado para animações de montagem/desmontagem - Animações de layout usam a prop
layoutdo Framer Motion (não cálculo manual de posição) -
will-changeaplicado apenas durante a animação, removido após - Sem gagueira no painel de Performance do Chrome DevTools (sem quadros longos > 16ms)
- Animações são interrompíveis (física de molas, não keyframes fixos com
ease) - View Transitions API tem fallback para navegadores não compatíveis
- Animações acionadas por rolagem usam
animation-timelineou ScrollTrigger (não event listeners de scroll)