PTENES
MÓDULO 2.2

📊 Charts & Datos

9 plantillas que transforman números en elementos visuales animados usando SVG puro e interpolate, sin Chart.js ni D3. Desde barras que crecen con stagger hasta un anillo de progreso y un contador numérico con coma.

9
Plantillas
45
Minutos
Inter
Nivel
SVG
Tipo
datos[ ] [45, 72, 58, 90] interpolate() frame → altura Ene Feb Mar Abr stagger: cada barra crece con delay = i × 3 frames video gráfico animado
1

📊 ¿Por qué SVG puro en lugar de Chart.js?

Las bibliotecas de gráficos como Chart.js y D3 están diseñadas para el navegador: dependen del DOM, los eventos y el estado interno. En Remotion, cada frame se calcula de forma independiente y determinista. SVG puro con interpolate es el enfoque correcto: el valor de cada elemento visual es una función directa del frame.

🎯 El modelo mental de los charts en Remotion

Cada elemento visual (barra, punto, arco) tiene una dimensión que crece según el frame. La fórmula es siempre la misma:

const progress = interpolate(frame, [startFrame, endFrame], [0, 1], {'{'}extrapolateRight: "clamp"{'}'});
const height = targetHeight * progress; // el SVG usa esta altura

✓ SVG puro: ventajas

  • ✓100% determinista — mismo fotograma, mismo píxel.
  • ✓Control total del timing: cada barra con su propio stagger.
  • ✓Cero dependencias adicionales: el bundle del proyecto es más pequeño.

✗ Chart.js en Remotion: problemas

  • ✗Las animaciones internas no se sincronizan con el frame de Remotion.
  • ✗Canvas puede renderizarse de forma diferente en headless Chrome.
  • ✗Es difícil personalizar el timing y el easing.
Paradigma
frame → dimensión
Herramienta
SVG + interpolate
Stagger
i × delay offset
Sin deps
Cero bibliotecas
2

📊 chart-animation — barras SVG con stagger

O chart-animation.tsx es la plantilla de referencia para gráficos de barras. Cada barra crece desde la base con un delay proporcional a su índice; el stagger da ritmo visual y separa la información visualmente.

chart-animation.tsx — barras con stagger templates/chart-animation.tsx
{data.map((point, i) => {
  const barHeight = (point.y / 100) * (chartHeight - padding * 2);

  const barProgress = interpolate(
    frame,
    [i * 3, 15 + i * 3],    // stagger
    [0, 1],
    { extrapolateRight: "clamp" }
  );

  const currentHeight = barHeight * barProgress;

  return (
    <rect
      key={i}
      x={barX}
      y={chartHeight - padding - currentHeight} /* crescer de baixo */
      width={barWidth}
      height={currentHeight}
      fill={colors[i % colors.length]}
      rx={4}
    />
  );
})}

📊 ¿Por qué y crece de abajo hacia arriba en SVG?

En SVG, el eje Y está invertido: y=0 es la parte superior, y=altura es la base. Para que una barra crezca desde la base, defines y = chartHeight - padding - currentHeight e height = currentHeight. A medida que aumenta currentHeight, la barra sube visualmente.

Timing de las barras (delay = i × 3):

B0

Barra 0: se anima del frame 0 al 15

inputRange [0, 15] — la primera en crecer.

B1

Barra 1: se anima del frame 3 al 18

inputRange [3, 18] — empieza 3 fotogramas después.

Bn

Barra n: inputRange [n×3, n×3+15]

Patrón universal de stagger para cualquier cantidad N de barras.

Stagger
i × 3 frames
SVG Y
Invertido (0=arriba)
Extrapolate
clamp obligatorio
Colores
i % colors.length
3

📈 line-chart — strokeDashoffset

El gráfico de líneas usa la técnica de stroke-dashoffset para dar la ilusión de una línea que se dibuja. El truco: definir stroke-dasharray igual a la longitud total del path, después animar dashoffset de longitud total a cero.

line-chart — técnica dashoffset templates/line-chart.tsx
// 1. Calcular pontos do polyline
const points = data.map((d, i) =>
  `${x0 + i * xStep},${y0 - d.value * scale}`
).join(" ");

// 2. Comprimento total (estimado ou via ref)
const totalLength = 600; // ou getTotalLength() em useRef

// 3. Animar o offset de comprimento a 0
const dashOffset = interpolate(
  frame,
  [0, 60],
  [totalLength, 0],
  { extrapolateRight: "clamp" }
);

return <polyline
  points={points}
  strokeDasharray={totalLength}
  strokeDashoffset={dashOffset}
  stroke="#60a5fa" strokeWidth=3 fill="none"
/>

💡 La técnica funciona con cualquier path SVG

No solo polyline: cualquier <path>, <circle> con stroke-dasharray puedes usar esta técnica. Así animas bordes circulares (circular-progress), firmas cursivas y cualquier forma dibujada a mano.

Técnica
dashoffset → 0
Funciona en
cualquier SVG stroke
Longitud
getTotalLength()
Easing
easeInOut recomendado
4

🥧 pie-chart y donut-chart — arcos SVG

Los gráficos circulares y de anillo son los más solicitados en videos de negocios. La técnica usa Comandos de arco SVG (A) calculados trigonométricamente a partir de los porcentajes de cada sector. El donut agrega un círculo blanco central para crear el hueco.

cálculo de segmento — función auxiliar helper de pie-chart
// converte ângulo → ponto no círculo
const polarToCartesian = (cx, cy, r, angle) => ({
  x: cx + r * Math.cos((angle - 90) * Math.PI / 180),
  y: cy + r * Math.sin((angle - 90) * Math.PI / 180),
});

// gera o "d" de uma fatia
const describeArc = (cx, cy, r, start, end) => {
  const s = polarToCartesian(cx, cy, r, start);
  const e = polarToCartesian(cx, cy, r, end);
  const flag = end - start > 180 ? 1 : 0;
  return `M ${cx} ${cy} L ${s.x} ${s.y} A ${r} ${r} 0 ${flag} 1 ${e.x} ${e.y} Z`;
};

📊 La bandera del arco (large-arc-flag)

El quinto parámetro del comando A é o large-arc-flag: 1 = usa el arco mayor (más de 180°), 0 = usa el menor. Olvidarlo hace que las porciones mayores al 50% se dibujen del lado equivocado.

flag = endAngle - startAngle > 180 ? 1 : 0
Comando SVG
M L A Z
Bandera Arc
>180° = 1
Donut
circle en la parte superior
Animación
ángulo final × progress
5

🔢 stat-counter — contador con coma

O stat-counter.tsx es uno de los componentes más solicitados en videos de marketing y resultados: un número grande que cuenta desde 0 hasta el valor objetivo, con separador de miles. Todo con interpolate + Math.floor + toLocaleString.

stat-counter — número formateado templates/stat-counter.tsx
const frame = useCurrentFrame();
const targetValue = 1234567;

const currentValue = interpolate(
  frame,
  [0, 60],
  [0, targetValue],
  {
    extrapolateRight: "clamp",
    easing: Easing.out(Easing.quad),
  }
);

// formatar com separador de milhar
const display = Math.floor(currentValue)
  .toLocaleString("pt-BR");

return <div>{display}</div>;

💡 Easing ease-out para contadores

Los contadores tienen más impacto con Easing.out(Easing.quad) — el conteo empieza rápido y se desacelera al llegar al valor final, dando énfasis al número de destino. Linear parece mecánico. ease-in hace lo contrario (lento-rápido) y rara vez funciona aquí.

Fórmula
interpolate → floor → locale
Easing
ease-out quad
Formato
toLocaleString()
Sufijo
K, M, % opcionales
6

⭕ circular-progress — anillo con dashoffset

O circular-progress.tsx usa la misma técnica del line-chart aplicada a un <circle> SVG. La circunferencia total es 2πr, y el dashoffset comienza allí y llega hasta cero a medida que aumenta el progreso. En el centro, una métrica numérica animada con stat-counter.

circular-progress — anillo animado templates/circular-progress.tsx
const radius = 80;
const circumference = 2 * Math.PI * radius; // ~502px

const progress = interpolate(
  frame, [0, 60], [0, targetPercent / 100],
  { extrapolateRight: "clamp" }
);

const dashOffset = circumference * (1 - progress);

return <circle
  r={radius} cx={100} cy={100}
  fill="none"
  stroke="#3b82f6"
  strokeWidth={12}
  strokeDasharray={circumference}
  strokeDashoffset={dashOffset}
  strokeLinecap="round"
  transform="rotate(-90 100 100)" /* começa no topo */
/>

📊 ¿Por qué rotate(-90)?

El SVG empieza a dibujar círculos a las 3 en punto (0°). El transform="rotate(-90 cx cy)" gira el punto de partida hacia arriba (las 12 en punto), que es donde esperamos que comience un anillo de progreso. Sin esto, el anillo empieza por la derecha.

Fórmula
2πr = circunferencia
Offset
circum × (1 - progress)
Inicio
rotate(-90) → arriba
Centro
texto superpuesto
7

📚 Biblioteca completa — Charts & Datos

PlantillaDescripciónTécnica SVG
chart-animation.tsx Barras SVG que crecen con stagger rect height
line-chart.tsx Línea trazada desde la izquierda dashoffset
pie-chart.tsx Gráfico circular con segmentos animados arc path M L A Z
donut-chart.tsx Gráfico de dona con métrica central arc + circle overlay
area-chart.tsx Área rellenada con degradado ruta cerrada + linearGradient
progress-bars.tsx Barras de progreso horizontal width% interpolado
stat-counter.tsx Contador con separador de miles interpolate + toLocaleString
comparison-chart.tsx Dos grupos lado a lado stagger por grupo
circular-progress.tsx Anillo de progreso con % circle dashoffset 2πr

📌 Resumen del módulo

✓
SVG puro con interpolate — sin Chart.js, determinista y controlable frame a frame.
✓
Stagger = i × delay en inputRange — cada barra/punto con timing independiente.
✓
dashoffset para líneas dibujadas — funciona en cualquier stroke SVG.
✓
Comandos Arc para gráficos de pastel y de dona — large-arc-flag es fundamental para segmentos >180°.
✓
stat-counter con ease-out — interpolate + floor + toLocaleString + easing quad.

Próximo módulo:

2.3 — Animación de contenido: listas con stagger, card-flip 3D, countdown, partículas y carrusel giratorio.