📖 Estructura narrativa — el arco del dato
Un Data-Story eficaz no empieza con el gráfico — empieza con el problema. El espectador necesita entender qué está en juego antes de ver el número. La secuencia de escenas crea automáticamente ese arco narrativo cuando ordenas bien el Series.
📈 El arco de 5 escenas
💡 Regla de 5–8 segundos por escena
Cada escena de datos debe durar entre 5 y 8 segundos. Menos de 5 s: el espectador no procesa el dato. Más de 8 s: el ritmo decae y parece una presentación de PowerPoint. Las transiciones cross-dissolve de 10–15 frames cubren el cambio sin interrumpir el flujo.
📊 Gráfico de barras animado — chart-animation
O chart-animation.tsx usa un array de valores y anima cada barra creciendo de 0 hasta su altura proporcional. El stagger entre barras hace que el gráfico parezca "llenarse": el ojo del espectador sigue la barra más alta, que normalmente representa el dato más importante.
const data = [42, 68, 55, 91, 37]; // valores % const maxH = 200; // px de altura máxima {data.map((val, i) => { const delay = i * 6; // stagger de 6 frames const barHeight = interpolate( frame, [delay, delay + 45], [0, (val / 100) * maxH], { extrapolateRight: "clamp", easing: Easing.out(Easing.quad) } ); // rótulo aparece quando barra chega ao topo const labelOpacity = interpolate( frame, [delay + 40, delay + 55], [0, 1], { extrapolateRight: "clamp" } ); return <div key={i} style={{ height: `${barHeight}px`, opacity: 1 }}> <span style={{ opacity: labelOpacity }}>{val}%</span> </div>; })}
✓ Barras que funcionan
- ✓Stagger de 4–8 frames entre barras: perceptible sin ser lento.
- ✓La etiqueta aparece cuando termina la barra: 15 frames después del retraso de la barra.
- ✓Easing.out para crecer: empieza rápido y desacelera al llegar a la cima.
✗ Errores de gráficos
- ✗Todas las barras crecen al mismo tiempo: se pierde el efecto de revelación.
- ✗La etiqueta aparece antes de que termine la barra: parece un error.
- ✗Easing.in para crecer: empieza demasiado lento y parece trabado.
🍩 Gráfico de dona de proporción
O donut-chart.tsx usa SVG con stroke-dasharray e stroke-dashoffset animados. Cada segmento es un <circle> con la longitud del arco calculada a partir del porcentaje. El reveal progresivo sigue la misma lógica de las barras: Easing.out, revelación de cada porción con un pequeño stagger.
Calcular la circunferencia y los offsets
const c = 2 * Math.PI * r — circunferencia del círculo. Para una porción del 42%, la longitud del arco es c * 0.42. O strokeDasharray é "arco restante" y el offset se rota para posicionarlo correctamente.
Animación de strokeDashoffset
Empieza con dashoffset = c (sector invisible) y anima hasta dashoffset = c - arco (sector completo). El resultado es el sector "dibujándose" en sentido horario.
El subtítulo aparece después del reveal
Cada color del gráfico de dona tiene una leyenda que aparece gradualmente cuando termina de aparecer la porción correspondiente. La leyenda y la porción quedan asociadas visualmente.
🔢 stat-counter y text-highlight combinados
La escena del dato central combina dos plantillas: stat-counter.tsx con el número animándose de 0 hasta el valor, y text-highlight.tsx que destaca una frase contextual con un background colorido que crece del 0% al 100% del width. Ambos entran en stagger: primero el número y luego el texto.
const frame = useCurrentFrame(); // número conta de 0 → 68% em 60 frames const pct = Math.round(interpolate( frame, [0, 60], [0, 68], { easing: Easing.out(Easing.cubic), extrapolateRight: "clamp" } )); // highlight cresce de 0 → 100% a partir do frame 50 const hlWidth = interpolate( frame, [50, 80], [0, 100], { extrapolateLeft: "clamp", extrapolateRight: "clamp" } ); return <AbsoluteFill style={{ display:"flex", flexDirection:"column", alignItems:"center", justifyContent:"center" }}> <span style={{ fontSize: 120, fontWeight: 800, color: "#fbbf24" }}>{pct}%</span> <div style={{ position: "relative" }}> <div style={{ position:"absolute", inset:0, background:"rgba(251,191,36,0.25)", width:`${hlWidth}%` }}/> <span>dos vídeos são assistidos sem som</span> </div> </AbsoluteFill>;
⚔️ Gráfico de comparación — comparison-chart
O comparison-chart.tsx muestra dos barras lado a lado que crecen de forma diferente: el argumento visual más poderoso para mostrar una diferencia. La regla de oro: la barra «mala» aparece primero, crece un poco y, entonces, la barra «buena» la supera de forma dramática.
✓ Comparación impactante
- ✓La barra negativa (roja) aparece primero: ancla baja.
- ✓La barra positiva (ámbar/verde) crece después y la supera: drama visual.
- ✓La etiqueta de diferencia porcentual aparece con spring en la parte superior de la barra más alta.
✗ Comparación débil
- ✗Ambas barras crecen al mismo tiempo: se pierde el efecto de «adelantamiento».
- ✗Colores similares en ambos lados: la comparación no queda clara.
- ✗Sin una etiqueta de diferencia, el espectador tiene que calcularla mentalmente.
🔀 Transiciones cross-dissolve entre escenas
El cross-dissolve es la transición ideal para Data-Story: lo bastante fluida para no interrumpir el razonamiento, pero marca claramente el cambio de escena. Se implementa superponiendo dos Sequence con overlap y animando las opacidades en sentidos opuestos durante los frames de superposición.
// Cena A: frames 0–90 | Cena B: frames 78–168 | overlap: 78–90 const DISSOLVE = 12; // frames de sobreposição return ( <AbsoluteFill> <Sequence from={0} durationInFrames={90}> <div style={{ opacity: interpolate(frame, [90 - DISSOLVE, 90], [1, 0], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }) }}> <CenaA /> </div> </Sequence> <Sequence from={90 - DISSOLVE}> <div style={{ opacity: interpolate(frame, [90 - DISSOLVE, 90], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }) }}> <CenaB /> </div> </Sequence> </AbsoluteFill> );
💡 10–15 fotogramas de disolución
Una disolvencia de 10 fotogramas (0.33 s a 30fps) casi no se percibe, pero suaviza el corte. Una disolvencia de 15 fotogramas (0.5 s) se nota y es más elegante. Por encima de 20 fotogramas empieza a parecer intencionalmente dramática; úsala solo si quieres ese efecto.
🏁 Resumen del módulo
Próximo módulo:
4.4 — Reels / Shorts: video vertical 9:16, typewriter, glitch, sound-wave, bokeh y recordatorio para suscribirse.