📝 A assinatura do interpolate()
O interpolate() recebe quatro argumentos: o valor de entrada (quase sempre frame), o inputRange, o outputRange e opções opcionais. Em troca, devolve um número calculado por interpolação linear entre os pontos.
import { interpolate, useCurrentFrame } from "remotion"; const frame = useCurrentFrame(); // interpolate(valor, inputRange, outputRange, opcoes?) const opacity = interpolate( frame, // entrada: número atual [0, 30], // inputRange: do frame 0 ao 30 [0, 1], // outputRange: de 0 a 1 (opacidade) { extrapolateLeft: "clamp", extrapolateRight: "clamp" } );
🎯 O que cada argumento faz
- •frame — o número que muda a cada quadro; pode ser qualquer variável numérica.
- •inputRange — a janela de frames onde a animação acontece (pelo menos 2 pontos).
- •outputRange — os valores correspondentes de saída; pode ser pixels, graus, decimais.
- •opcoes — controla o que acontece fora do inputRange (clamp, extend, wrap).
🗺️ inputRange e outputRange — domínio e contradomínio
Pense em inputRange como o domínio (quais frames fazem parte da animação) e outputRange como o contradomínio (quais valores saem). O interpolate() encontra o ponto proporcionalmente equivalente dentro do outputRange.
📊 Exemplos de mapeamento
[0, 30] → [0, 1]— fade-in: opacidade cresce de 0 a 1 em 1 segundo (30fps).[0, 30] → [0, 300]— slide: translateX vai de 0 a 300px em 1 segundo.[0, 30] → [0.5, 1]— scale: objeto começa na metade do tamanho e cresce para 100%.[0, 30] → [360, 0]— rotação inversa: começa girado 360° e vai para 0.
const opacity = interpolate(frame, [0, 20], [0, 1], { extrapolateRight: "clamp" }); const translateY = interpolate(frame, [0, 20], [40, 0], { extrapolateRight: "clamp" }); return ( <div style={{ opacity, transform: `translateY(${translateY}px)` }}> Conteúdo que entra de baixo </div> );
💡 Dica: ranges não precisam começar em 0
Você pode usar [45, 60] como inputRange para que a animação comece 1,5s depois do início do vídeo. O que está fora do range é controlado pela opção extrapolate.
🔒 extrapolate: clamp vs extend
O que acontece quando frame sai do inputRange? Por padrão, o interpolate() extende a linha além dos pontos definidos — o que pode fazer a opacidade passar de 1 ou ir abaixo de 0. O clamp evita isso.
✓ O que FAZER
- ✓Usar
extrapolateRight: "clamp"em opacidade para nunca passar de 1. - ✓Usar
extrapolateLeft: "clamp"para segurar o valor antes do início da animação. - ✓Deixar
extend(padrão) só quando a extrapolação faz sentido (ex.: posição que continua).
✗ O que NÃO fazer
- ✗Deixar opacidade sem
clamp— no frame 60,[0,30]→[0,1]devolve 2 (invisível no CSS). - ✗Esquecer o
extrapolateLeftquando a animação começa tarde (frame 45+). - ✗Usar opções diferentes de
clamp/extend/wrap/identity— não existem.
// SEM clamp: frame=60 → opacity=2 (bug visual) const opacityBug = interpolate(frame, [0, 30], [0, 1]); // COM clamp: frame=60 → opacity=1 (correto) const opacity = interpolate(frame, [0, 30], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp", });
🔑 Múltiplos keyframes — fade-in / hold / fade-out
O inputRange e o outputRange aceitam mais de dois pontos. Isso cria keyframes: a animação passa por cada par [frame → valor] em sequência. É como o timeline de um editor de vídeo, mas em código.
frame 0 → opacity 0
Elemento invisível no início.
frame 15 → opacity 1
Fade-in completo em 0,5s.
frame 75 → opacity 1
Permanece totalmente visível até 2,5s — o "hold".
frame 90 → opacity 0
Fade-out de 0,5s antes do corte.
const opacity = interpolate( frame, [0, 15, 75, 90], // 4 keyframes [0, 1, 1, 0], // entra, segura, sai { extrapolateLeft: "clamp", extrapolateRight: "clamp" } );
🎨 Easing — movimento natural
Por padrão, o interpolate() faz uma interpolação linear — velocidade constante do começo ao fim. Para movimento natural, use a opção easing com funções do módulo Easing do Remotion (compatível com React Native).
🎯 Easings mais usados
- •
Easing.out(Easing.ease)— começa rápido, desacelera no final. Clássico para entradas. - •
Easing.in(Easing.ease)— começa devagar, acelera. Bom para saídas. - •
Easing.inOut(Easing.ease)— suave nos dois extremos. Sólido para transições. - •
Easing.bezier(0.25, 0.1, 0.25, 1)— controle total com curva cúbica. - •
Easing.cubic— alternativa rápida ao bezier com curva cúbica padrão.
import { interpolate, Easing, useCurrentFrame } from "remotion"; const frame = useCurrentFrame(); const translateY = interpolate(frame, [0, 25], [60, 0], { extrapolateRight: "clamp", easing: Easing.out(Easing.cubic), });
💡 Linear vs Easing na prática
Uma animação linear parece "mecânica" — objeto se move em velocidade robótica. Com Easing.out, o elemento entra com energia e desacelera naturalmente, como se obedecesse à física. Essa diferença é o que separa protótipos de vídeos profissionais.
🧩 Padrões: fade, slide e scale
Com interpolate() em mãos, três padrões cobrem 90% das animações de UI de vídeo: fade (opacidade), slide (translateX/Y) e scale. Combinando os três, você constrói qualquer entrada ou saída de elemento.
✓ Os três padrões essenciais
- ✓Fade:
opacity = interpolate(frame, [0,20], [0,1], {clamp}) - ✓Slide X:
transform: translateX(${x}px)com x de −200 a 0. - ✓Scale:
transform: scale(${s})com s de 0.8 a 1.
✗ Erros comuns
- ✗Usar CSS transitions ou keyframes — conflita com o modelo de render do Remotion.
- ✗Combinar
scaleetranslateXsemtransformem string única (se apagam). - ✗Usar
width/heightanimados em vez detransform: scale(causa reflow).
const opts = { extrapolateRight: "clamp", easing: Easing.out(Easing.cubic) } as const; const opacity = interpolate(frame, [0, 20], [0, 1], opts); const x = interpolate(frame, [0, 20], [-60, 0], opts); const scale = interpolate(frame, [0, 20], [0.9, 1], opts); return ( <div style={{ opacity, transform: `translateX(${x}px) scale(${scale})`, }}> Conteúdo com entrada suave </div> );
💡 Combine sempre no mesmo transform
Quando você usa transform duas vezes no mesmo objeto de estilo, o segundo sobrescreve o primeiro. Sempre concatene tudo numa string só: `translateX(${x}px) scale(${s})`.
📌 Resumo do módulo
Easing.out(Easing.cubic) torna o movimento natural; combine com os padrões fade/slide/scale.Próximo módulo:
1.3 — spring() & composição: física de mola, overshoot natural e como empilhar cenas com Sequence e AbsoluteFill.