wandres.dev
LOTTIE Y AFTER EFFECTS · La animación del diseñador

El pipeline desde After Effects: Bodymovin y el contrato con diseño

Cómo se exporta un Lottie, qué opciones del exportador cambian el resultado, y el contrato que hay que acordar con quien anima antes de que empiece, no después.

⏱ 18 min

El fallo más caro de un proyecto con Lottie no ocurre en el navegador: ocurre tres semanas antes, cuando alguien anima cuarenta segundos con efectos que el formato no soporta y nadie lo comprueba hasta la integración. El exportador no avisa: ignora lo que no entiende y produce un fichero válido que se ve distinto. La única defensa es un contrato acordado antes de la primera animación y un exportado de prueba desde el primer día.

🎯 Al terminar esta lección sabrás
  • Ejecutar el flujo de exportación con Bodymovin y entender qué hace cada opción.
  • Preparar una composición de After Effects para que exporte sin sorpresas.
  • Redactar el contrato técnico con diseño en términos que un animador entienda.
  • Montar una revisión automatizada que rechace un fichero antes de que llegue al repositorio.

El exportador

Bodymovin es una extensión de After Effects que recorre la composición y serializa lo que encuentra al JSON descrito en la lección anterior. LottieFiles distribuye una versión con su marca y un flujo de subida a su plataforma; el motor es el mismo proyecto de Hernán Torrisi y el formato de salida es idéntico.

El flujo desde el lado del ingeniero es corto: se instala la extensión, se abre el panel desde el menú de extensiones, se selecciona la composición y se pulsa Render. Lo que importa son las opciones, porque cada una cambia el fichero de forma que se nota.

Glyphs y Hidden. Glyphs convierte el texto en trazados vectoriales. Es lo que quieres en el noventa y nueve por ciento de los casos, porque la alternativa es que el reproductor intente resolver una fuente que el navegador puede no tener. El coste es que un texto largo vectorizado añade decenas de trazados. Hidden incluye las capas ocultas; salvo que sepas exactamente por qué, déjalo desactivado: exportar capas que nadie ve es peso y trabajo por fotograma a cambio de nada.

Compressed y assets. Puedes incrustar las imágenes en base64 dentro del JSON o dejarlas como ficheros aparte junto al .json. Incrustar simplifica el despliegue y penaliza el peso en torno a un tercio; dejarlas fuera te obliga a servir la carpeta entera con las rutas correctas. La tercera opción, y normalmente la mejor, es no tener imágenes.

Standalone y demo. Standalone empaqueta el reproductor junto a la animación en un solo .js. Es cómodo para enviar una prueba por correo y una idea terrible para producción: duplicas el reproductor en cada animación. Demo genera un HTML de previsualización, que sí es útil para revisar sin montar nada.

Split. Parte animaciones muy largas en varios ficheros. Rara vez es la respuesta correcta; si necesitas partir, casi siempre lo que necesitas es acortar.

Y la exportación a .lottie, que es un contenedor distinto y tiene su propia lección.

Preparar la composición

Estas son las decisiones que se toman en After Effects y determinan el resultado. Cada una tiene una razón derivada de la estructura del formato.

La composición manda en el tamaño y en la velocidad. Los tiempos van en fotogramas de la composición: una composición a 60 fps con una animación de tres segundos tiene ciento ochenta fotogramas de resolución temporal. A 30 fps, noventa. No se gana calidad subiendo la composición a 60 si el movimiento es lento, y sí se dobla el número de keyframes horneados de cualquier expresión.

Los efectos hay que decidirlos antes. La lista soportada es corta y todo lo demás desaparece en silencio. Lo que en After Effects se resuelve con un efecto —un resplandor, un desenfoque, una distorsión— en Lottie hay que resolverlo con formas, gradientes y opacidades, o no resolverlo. Ese es un cambio de método de trabajo, no un ajuste.

Las expresiones se hornean o se pierden. El exportador tiene una opción para convertirlas a keyframes. Convertir un wiggle de dos segundos a 60 fps produce ciento veinte keyframes en esa propiedad; si la propiedad es un trazado, cada keyframe lleva la geometría completa. Es el mecanismo por el que un fichero pasa de treinta kilobytes a cuatro megabytes sin que nadie entienda por qué.

Los repetidores son la trampa de rendimiento. Un repetidor no pesa, pero multiplica el trabajo por fotograma. Un diseñador que consigue un efecto bonito con un repetidor de treinta copias dentro de otro de seis acaba de crear ciento ochenta trazados que hay que dibujar sesenta veces por segundo. Hay que hablarlo antes.

Los mattes y las máscaras animadas cuestan. Un track matte obliga al reproductor a componer dos capas con una operación de recorte. En el renderizador de SVG eso se traduce en un clipPath o una mask por capa afectada, y las máscaras son de lo más caro que se puede pedir a un motor de SVG.

Traza lo que puedas. Cada capa de forma que puedas convertir en una primitiva parametrizada —un rectángulo, una elipse, una estrella— en lugar de un trazado con veinte vértices es un ahorro directo en bytes y en tiempo de evaluación.

⚠️
Lo que se ve en el panel de previsualización no es lo que verá el navegador

La previsualización de After Effects usa el motor de After Effects. El fichero exportado lo dibuja otro intérprete completamente distinto. La única validación que cuenta es abrir el .json exportado en un reproductor web, en un dispositivo parecido al del usuario. Hay que hacerlo el primer día con una prueba de treinta segundos, no al final con la animación terminada.

El contrato con diseño

Escribe esto una vez, en el idioma de quien anima, y pégalo en el brief de cada pieza. La lista es corta a propósito: una lista de treinta puntos no se lee.

Sí: formas, trazados, trazos, rellenos, gradientes, trim paths, máscaras sencillas, precomposiciones, texto vectorizado.

No: efectos que no sean relleno o corrección de color, plugins de terceros, desenfoque de movimiento, partículas, capas 3D con cámara, modos de fusión exóticos.

Con cuidado: expresiones, repetidores anidados, track mattes, imágenes incrustadas.

Presupuesto: menos de sesenta trazados visibles a la vez. Bucle de menos de cinco segundos. Composición a 30 fps salvo que el movimiento sea muy rápido.

Entrega: el .json exportado y una captura de vídeo de la previsualización de After Effects para poder comparar.

Ese último punto es el que más discusiones evita. Cuando el resultado en el navegador no coincide, tener el vídeo de referencia convierte una conversación de opiniones en una comparación de fotogramas.

Una revisión automatizada

Un script corto que lea el JSON y aplique el presupuesto detecta el noventa por ciento de los problemas antes de que nadie integre nada. Este cuenta capas, trazados y factor de repetición, y falla si se pasa del límite.

// revisar-lottie.mjs — node revisar-lottie.mjs animacion.json
import { readFileSync } from "node:fs";

const LIMITE_TRAZADOS = 60;
const LIMITE_KEYFRAMES = 4000;

const datos = JSON.parse(readFileSync(process.argv[2], "utf8"));

let trazados = 0;
let keyframes = 0;
const avisos = [];

function recorrerFormas(items, factor) {
  for (const item of items) {
    if (item.ty === "gr") {
      let sub = 1;
      const rep = item.it?.find((i) => i.ty === "rp");
      if (rep) {
        sub = rep.c?.a === 0 ? rep.c.k : 1;
        avisos.push(`Repetidor con ${sub} copias`);
      }
      recorrerFormas(item.it ?? [], factor * sub);
    } else if (["sh", "rc", "el", "sr"].includes(item.ty)) {
      trazados += factor;
    }
    contarKeyframes(item);
  }
}

function contarKeyframes(nodo) {
  if (nodo == null || typeof nodo !== "object") return;
  if (nodo.a === 1 && Array.isArray(nodo.k)) keyframes += nodo.k.length;
  for (const valor of Object.values(nodo)) {
    if (typeof valor === "object") contarKeyframes(valor);
  }
}

for (const capa of datos.layers ?? []) {
  if (capa.ty === 4) recorrerFormas(capa.shapes ?? [], 1);
  if (capa.ty === 5) avisos.push(`Capa de texto sin vectorizar: ${capa.nm}`);
  if (capa.hasOwnProperty("tt")) avisos.push(`Track matte en la capa ${capa.nm}`);
  contarKeyframes(capa.ks);
}

const duracion = (datos.op - datos.ip) / datos.fr;
console.log(`Duracion: ${duracion.toFixed(2)} s a ${datos.fr} fps`);
console.log(`Trazados dibujados: ${trazados}`);
console.log(`Keyframes totales: ${keyframes}`);
avisos.forEach((a) => console.log(`  aviso: ${a}`));

if (trazados > LIMITE_TRAZADOS || keyframes > LIMITE_KEYFRAMES) {
  console.error("Fuera de presupuesto");
  process.exit(1);
}

Engánchalo a un hook de pre-commit o a la CI sobre la carpeta de animaciones. La conversación cambia por completo cuando el límite lo pone un script y no una persona: deja de ser una opinión sobre el trabajo de alguien y pasa a ser una restricción del sistema, que es como hay que plantearla desde el principio.

El fallo silencioso del exportador es el defecto de diseño que hay que compensar con proceso

Un compilador que encuentra una construcción que no soporta se para y te dice dónde. Bodymovin no: recorre la composición, escribe lo que entiende, omite lo que no y produce un fichero perfectamente válido que reproduce una versión distinta de la animación. Desde el punto de vista del sistema es la peor combinación posible, porque el error no se manifiesta como un error sino como una diferencia estética, y una diferencia estética se descubre tarde, la descubre la persona equivocada y se discute como si fuera una cuestión de gusto. El origen del problema es estructural y no se va a arreglar: After Effects es un superconjunto enorme del formato, el mapeo entre ambos es parcial por definición, y un exportador que fallara ante cada elemento no soportado sería inutilizable porque casi ninguna composición real está limpia. Lo que se puede hacer es mover la detección hacia delante en el tiempo, y ahí hay exactamente dos palancas. La primera es exportar el primer día: una prueba de diez segundos con la técnica que se va a usar en toda la pieza, integrada de verdad en el navegador de destino, revela en una tarde el problema que de otro modo aparece en la semana de la entrega. La segunda es el análisis automático del fichero, que no detecta lo que falta —eso es imposible, porque la información ya no está— pero sí detecta lo que sobra: los repetidores, los mattes, los keyframes horneados, el texto sin vectorizar. Entre las dos cubren casi todo. Lo que nunca funciona es confiar en que el animador conozca las limitaciones, porque son limitaciones de un formato que no usa y que no se parecen a nada de su herramienta. El contrato hay que escribirlo desde el lado que conoce la restricción, y hay que verificarlo con una máquina, exactamente igual que se hace con cualquier otro contrato de interfaz.