Communitygithub.com

MooT020/gsap-explainer

Crea un vídeo explicativo animado con GSAP de calidad Kurzgesagt: un archivo HTML autónomo que se reproduce como un vídeo de YouTube producido: mundos en capas, poblaciones de personajes, coreografía con sensación física, una mascota anfitriona voladora y un reproductor interactivo. Úsalo cuando el usuario quiera un vídeo explicativo/de YouTube de alta producción, un 'vídeo GSAP' o un paso adelante respecto a un vídeo explicativo solo con CSS.

¿Qué es gsap-explainer?

Esta habilidad proporciona un marco completo para construir vídeos explicativos animados de alta calidad al estilo Kurzgesagt utilizando GSAP, todo en un único archivo HTML autónomo. Está diseñada para crear contenido de nivel vídeo de YouTube producido, no simples presentaciones de diapositivas, incorporando múltiples escenas con línea de tiempo, una mascota anfitriona voladora persistente, mundos de gradiente con profundidad, poblaciones de personajes, un efecto de cámara con viñeta y grano, y un reproductor interactivo con capacidad de búsqueda. La habilidad incluye un archivo de referencia funcional (`scaffold.html`) con cinco escenas de ejemplo, un conjunto completo de plugins GSAP gratuitos (como DrawSVG, MotionPath, MorphSVG, SplitText, y Physics2D) y un script de Python (`inline-gsap.py`) para incluir GSAP automáticamente. La metodología principal es 'adaptar, no inventar', proporcionando una biblioteca de patrones de coreografía probados como caídas con rebote, colisiones de superposición forzada, transformaciones de vertido, revelaciones con efecto flip y más, junto con un riguroso proceso de desarrollo que comienza con un guion gráfico, luego la copia del esqueleto, la sustitución escena por escena, y finalmente el control de calidad con fotogramas congelados. Es ideal para desarrolladores y creadores de contenido que buscan producir vídeos explicativos atractivos y de aspecto profesional sin depender de software de edición de vídeo tradicional.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/MooT020/takhayyal-video-skills/tree/HEAD/plugins/kurzgesagt-explainer/skills/gsap-explainer

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Explicador GSAP: el nivel de vídeo producido

Construye un explicador HTML/SVG/GSAP autónomo que se lee como una animación de YouTube producida, no como una presentación de diapositivas: una línea de tiempo de GSAP por escena que impulsa una coreografía con sensación física, una mascota anfitriona voladora persistente, mundos de gradiente en capas con profundidad, poblaciones de personajes, una 'cámara' con viñeta y grano, y un reproductor con capacidad de búsqueda. Usa un arnés solo CSS para incrustaciones de embudo pequeñas; usa ESTO para vídeos de contenido de nivel YouTube.

La construcción de referencia es scaffold.html en esta carpeta de habilidad: un ejemplo funcional de 5 escenas (tema: 'Cómo el interés compuesto hace bola de nieve') con cada patrón a continuación en contexto, retención + superposición cero pasada. Viene con GSAP eliminado: ejecuta python3 inline-gsap.py scaffold.html una vez (obtiene GSAP 3.13 en un vendor/ ignorado por git, luego lo incluye) y abre el archivo; debe reproducirse. Léelo cuando un patrón a continuación no esté claro.

Empieza aquí: el camino que no puede fallar

  1. Escribe el guion de tomas PRIMERO como un documento markdown: por escena: marca de tiempo, duración, VISUAL, texto EN PANTALLA, línea de VO. Termina con una lista de verificación de precisión y verifica cada afirmación en ella. Las duraciones de las escenas se convierten en el array SCENES; las líneas de VO se convierten en la transcripción sr-only.
  2. Copia scaffold.html a <topic>.html. Tiene todos los problemas previamente solucionados: reloj del arnés, cromo de búsqueda, vuelos del anfitrión, fondos del mundo, superposiciones de cámara, personajes de población, movimiento reducido, transcripción. Ejecuta inline-gsap.py en él y ábrelo antes de tocar nada; debe reproducirse.
  3. Reemplaza las escenas una a la vez, manteniendo los cinco ejemplos funcionales como tu fuente de modismos hasta que cada uno sea reemplazado: S0 = gancho oscuro con revelación flip; S1 = caída con rebote físico; S2 = vuelo vertido/motionPath + DrawSVG; S3 = la prueba de colisión de superposición forzada (el patrón cumbre); S4 = retención de CTA. Actualiza SCENES, FL, ACTS, CH_STARTS juntos: son estructuras paralelas indexadas por escena.
  4. QA cada escena con fotogramas congelados (ver QA), corrige, luego publica (archivo autónomo).

Nunca escribas la coreografía de una escena desde cero cuando un patrón a continuación coincida: adapta el patrón. Así es como alcanzas el nivel independientemente del modelo.

Contrato de arquitectura (ya cableado en el esqueleto)

  • Escenario fijo 800×500 escalado al contenedor (fitScale). El reloj de la escena es setTimeout (array SCENES, segundos por escena; última entrada 999 = retención de CTA; advance() llama a done() en él).
  • El texto/chips/leyendas entran a través de primitivas CSS (.fu fade-up, .pp pop, .fi fade-in) con animation-delay en línea: baratos y reproducibles. La coreografía del héroe es GSAP: runScene(i) (llamado desde showScene) elimina la línea de tiempo anterior y construye gsap.timeline() a partir de FL[i] (vuelo del anfitrión) + ACTS[i] (acto de la escena).
  • Cada ACTS[i] DEBE comenzar con reinicios gsap.set(...) para todos los elementos que toca: las escenas se reactivan en la reproducción/búsqueda y las interpolaciones eliminadas dejan estilos en línea obsoletos.
  • Los elementos propiedad de GSAP obtienen la clase g-hero (o viven dentro de uno) y nunca llevan .fu/.pp/.fi: un propietario por elemento.
  • pause()/resume() llaman a curTl.pause()/play(); el lado CSS se congela mediante la clase .paused. La navegación siempre reanuda la reproducción (una escena recién cortada en pausa se sienta en entradas con opacidad 0: nunca 'buscar y permanecer en pausa').
  • Reproductor: clic para buscar en la barra de progreso (sceneAt(frac)), botones anterior/siguiente, teclas ←/→, marcas de capítulos (CH_STARTS), reproducción automática al desplazarse, pausa automática al ocultar pestaña.
  • El entregable es la pista visual silenciosa (el maestro permanece en silencio); la VO se envía como una variante de vista previa separada <name>-vo.html construida por el pipeline de ElevenLabs (ver Producción de VO). La transcripción sr-only ES el guion de VO. Reajustar el tiempo a una lectura = EXTENDER SCENES[i] para recortar +1.5–2s (extender nunca deja colgados los tiempos; solo los recortes lo hacen).

La biblioteca de patrones (adapta, no inventes)

Todos estos existen textualmente en scaffold.html: copia el más cercano.

  • Vuelo del anfitrión: FL[i] = [[fracción, x, y, apuntando], ...]. El primer punto de ruta = el último de la escena anterior (cortes sin costura). Las piernas largas se inclinan automáticamente a través de MotionPath (en fly()). La punta del lápiz se sienta en un desplazamiento del actor ≈ (−10, +95): para apuntar a un objetivo, estaciona al anfitrión arriba a la derecha de él. Envía al anfitrión fuera del escenario (x=850) cuando una escena necesite el encuadre.
  • Caída con peso: gsap.set(els,{y:-300,opacity:0}) luego .to(els,{y:0,opacity:1,ease:'bounce.out',stagger:.09}). El escalonamiento + rebote ES la sensación física. (layMarbles empaqueta filas dentro del recipiente; el ancho de la fila es 168, no 180: más ancho y las caídas atraviesan la pared).
  • Colisión de superposición forzada (la prueba cumbre): dos barras caen en una sola pista que no puede contener a ambas; la segunda intenta esquivar (x yoyo), falla, se asienta; el segmento de superposición aparece con back.out y brilla (boxShadow yoyo repeat:-1); luego dos secuaces de personajes con ambas insignias aparecen dentro de él. Intención → fracaso → consecuencia es lo que lo hace sentir vivo.
  • Vertido/transformación: el contenedor rota (transformOrigin en el pico), los contenidos vuelan uno por uno en arcos motionPath ({path:[{x,y},{x,y}],curviness:1.6}, ease:'power1.in'), aterrizan en una fila, se funden en la nueva forma dibujada con DrawSVG.
  • Revelación flip: aparece una ✓ tentadora (back.out(2.4)), se menea, luego se intercambia por la ✗ que entra con fuerza (scale:3→1, power4.out) + un destello de fondo (backgroundColor yoyo).
  • Tentación luego destrucción: la respuesta brilla/pulsa (scale yoyo ×3), luego muere (opacity:.25, scale:.92, rotation:-3, power2.in); la respuesta correcta se sella después.
  • Sello contundente: gsap.set(stamp,{opacity:0,scale:2.6,rotation:-14}) → .to({opacity:1,scale:1,rotation:0,duration:.35,ease:'power4.out'}).
  • DrawSVG: gsap.set(path,{drawSVG:'0%'}) → .to({drawSVG:'100%'}); retroceso = dibujar al 72% luego invertir rápido. DrawSVG sobrescribe stroke-dasharray: las líneas discontinuas se renderizan sólidas mientras se dibujan; diseña en consecuencia.
  • Población como personajes (el movimiento más característico de Kurzgesagt): fábrica de mini-personajes minion(size, badges): las cantidades son pequeños personajes, no puntos. Enjambre ambiental de 3 personajes en bucles CSS de 35–55s; los grupos contienen su elenco de personajes; el momento de prueba son personajes que usan ambas insignias.
  • Corte de escena con barrido (incorporado en runScene): dos paneles sesgados (el acento lidera, la tinta sigue .09s) barren el escenario en cada corte. Déjalo; es la ganancia más barata de 'transiciones reales'. Ideas de escenas ricas en accesorios que vale la pena robar: un personaje de página viviente, una ruina de rotulador, un archivador, una aguja de medidor, una carrera de barras de progreso.

El conjunto de plugins gratuitos (GSAP 3.13: TODOS gratuitos desde la adquisición de Webflow)

inline-gsap.py obtiene e incluye el núcleo + DrawSVG + MotionPath + MorphSVG, SplitText, Physics2D, PhysicsProps, CustomEase, CustomWiggle, CustomBounce, Flip, ScrambleText. Todo tiene licencia gratuita. inline-gsap.py <file> inyecta todo + un bloque registerPlugin en el marcador <!--GSAP_INLINE-->; --refresh intercambia el conjunto en un archivo ya incluido. Patrones probados (todos viven en el esqueleto):

  • Cascada de caracteres SplitText: divide UNA VEZ al inicio a través de un registro (splitOnce(key,sel) con caché en SPL{}: volver a dividir en cada re-ejecución de escena anida tramos). Pateador: caracteres desde {opacity:0,y:14}, escalonamiento .016, inicio ≤.15s. Palabra héroe: caracteres desde {y:-64,rotation:-9} con back.out(1.9) escalonamiento .07; o {scale:2.7} power4 escalonamiento .11 = sello contundente. Las escenas se ocultan mediante opacidad (no display:none) para que la división en tiempo de inicio sea segura.
  • Bloqueo de definición ScrambleText: una línea de recompensa se mezcla en su lugar: scrambleText:{text:'≥ 1',chars:'<>=~≠≤≥',speed:.6}. Prefiere escapes JS \u para símbolos en cadenas JS. Los conjuntos de caracteres temáticos (símbolos matemáticos para definiciones) se leen mejor que 'upperCase': una mezcla larga de mayúsculas aleatorias se lee como un error de carga.
  • Asentamiento CustomWiggle: CustomWiggle.create('wigSettle',{wiggles:4,type:'easeOut'}), luego rotation:'+=10', ease:'wigSettle': oscila y REGRESA AL INICIO, por lo que los valores relativos nunca se acumulan en las repeticiones. Úsalo para: aterrizajes de sellos, reacciones de personajes, el golpeteo del lápiz del anfitrión al llegar (if(wp[i][3]&&!wp[i-1][3]) en fly()).
  • Caída CustomBounce con compresión: CustomBounce.create('thud',{strength:.58,squash:2.4}) crea facilidades emparejadas 'thud'+'thud-squash'. El helper drop(tl,targets,time,dur,stagger) ejecuta 3 interpolaciones sincronizadas: pop de opacidad, y con 'thud', scaleX:1.45,scaleY:.55 con 'thud-squash' (transformOrigin:'50% 100%' en el reinicio). Estrictamente mejor que bounce.out: la compresión ES el peso.
  • Explosión Physics2D: burst(tl,scene,x,y,n,time,colors): partículas de celebración/escombros donde el aterrizaje no importa (picos de colisión, sellos de victoria). Ángulos/velocidades sembrados por índice ((i*53)%140) = reproducción idéntica, sin Math.random. Elimina .pfx obsoleto al reingresar; desvanece antes del final de la escena para que nada persista.
  • Fusión MorphSVG: el mejor movimiento de Kurzgesagt: N objetos 'se convierten' en el concepto. Los elementos aterrizan en una fila → una ruta de cápsula se desvanece sobre ellos → morphSVG a la silueta de flecha mientras fill se interpola ('mismos objetos, nueva forma', literalmente). El reinicio necesita gsap.set(path,{morphSVG:ORIGINAL_D}): una ruta morph guarda su d mutado.
  • Flip: NO lo hagas aquí: en un escenario de coordenadas absolutas fijas 800×500 siempre conoces el delta; una interpolación simple y: es determinista bajo tl.pause(t) QA, mientras que la medición en tiempo de ejecución de Flip rompe la limpieza de fotograma congelado (y las devoluciones de llamada no se disparan en búsquedas suprimidas). Flip solo vale la pena en diseños de reflujo reales (listas impulsadas por DOM, contenedores responsivos). Un tiempo de 'reclamar el lugar vacante' es una interpolación de delta conocido.

Artesanía de activos (patrones de 10 pases: cómo los accesorios dejan de parecer divs estilizados)

Inmersión profunda: la disciplina completa de generación de activos (orden de construcción, fábricas, contratos SVG, puertas de calidad) vive en la habilidad explicador-activos: úsala siempre que CREES o reconstruyas un activo; esta sección es la referencia rápida.

  • La pegatina de una receta: profundidad enteramente de box-shadow en capas: gota de tinta dura hacia abajo a la derecha (3px 3px 0 var(--ink)) + inset 0 2px 0 rgba(255,255,255,.3-.5) brillo superior + inset 0 -3px 0 rgba(0,0,0,.1) sombra inferior + inset 0 0 0 1-2px rgba(255,255,255,.14) borde troquelado. Las inserciones translúcidas funcionan con CUALQUIER color de fondo, por lo que un solo pase CSS en .xchip/.qbar/.stamp/.l3 span eleva cada variante, clara y oscura. Mantén una escala de radio (sm 10 / base 13 / lg 16) y UNA dirección de luz (superior izquierda) en toda la película.
  • Dos tonos para cualquier relleno plano: intercambia background:rgba(...) por linear-gradient(180deg, más claro, base) + las inserciones de brillo/sombra. El color semántico sobrevive; la superficie se lee iluminada.
  • Receta de recipiente artesanal (cubos/jarras/tazas): elipse de sombra base → cuerpo de gradiente → 2 bandas de aro cónicas con resaltado blanco de 1px → anillo de borde + una ELIPSE DE APERTURA INTERNA MÁS OSCURA (esa elipse oscura es lo que hace que una boca se lea en 3D) → curva especular suave. Interpola los puntos finales de la banda a lo largo de los lados del trapezoide.
  • Arte lineal artesanal en un selector: filter:drop-shadow(0 1.5px .5px rgba(0,0,0,.17)) estático en todos los trazos dibujados le da a cada flecha/cuadrado un lado inferior de dos tonos y se REVELA con la animación DrawSVG (el filtro es independiente de dashoffset).
  • Decora accesorios impulsados por GSAP con pseudoelementos: ::before/::after (líneas pautadas, tiras adhesivas, grietas, líneas de menisco) montan la transformación de la línea de tiempo automáticamente: cero coreografía nueva, cero cambio de huella. Rastrea qué pseudos están 'ocupados' por clase: las colisiones son silenciosas.
  • Fábrica de personajes: ids solo en singletons: el anfitrión (una instancia) puede llevar gradientes/especulares con sufijo uid; una fábrica con muchas inclusiones (minipersonajes) debe permanecer SIN id (solo rellenos simples) o los ids se duplican en todo el documento.
  • Preserva el contrato de coreografía mientras recreas: construye un inventario de selectores del guion PRIMERO; los selectores posicionales son minas terrestres (.bkt3 path = PRIMERA ruta debe permanecer como el cuerpo interpolado: lidera con elipses, no con rutas). Las nuevas transformaciones decorativas van en <g>s envolventes.
  • Advertencia de brillo seguro para texto: en chips que llevan SplitText/texto héroe, el brillo debe ser box-shadows insertados (pintar DEBAJO del texto), nunca una superposición ::before posicionada (pinta SOBRE los caracteres y los oscurece).
  • Receta de pila de papel + esquina doblada (cualquier accesorio de hoja): 2 rectángulos traseros desplazados (±0.6–1.5° rotación, crema más oscura, overflow:visible en el svg), triángulo de sombra de esquina cortada + solapa doblada, una regla de margen, un camino de brillo superior izquierdo. Huella sin cambios, solo sangrado visual.
  • Kit frontal de cajón/mueble: rectángulo frontal + tira de brillo superior + placa de etiqueta + barra de manija empotrada + línea de sombra de profundidad entre unidades; parametriza la paleta para la unidad resaltada, mantén su clase de animación.
  • Nube vectorial de 2 tonos: elipse base teñida + 3 círculos blancos superpuestos + una elipse superior más brillante; recolora el tinte base por variante de estado de ánimo.
  • Superposición de tarjeta de plano: svg hijo posicionado absolutamente (cuadrícula pautada tenue + 4 marcas de esquina) como primer hijo de una tarjeta: textura de dibujo técnico con efecto cero en la clase de interpolación de la tarjeta o en el hijo de texto.

La capa de cine (patrones de nivel Kurzgesagt)

  • Rig de cámara #xplCam: un envoltorio solo de contenido DENTRO de #xplStage que contiene las escenas (capas de entorno, actor, vig/grano permanecen fuera). Acercamientos por tiempo en momentos clave (~1.02–1.05, transformOrigin en el héroe), alejamientos en revelaciones, reinicia la escala a 1 en runScene cada corte. Nunca escales #xplStage en sí mismo: eso es de fitScale. La escena cumbre se gana UNA penetración lenta e ininterrumpida en todo su acto. Verifica el riesgo de recorte contra los límites VISIBLES de la píldora/accesorio, no los contenedores de ancho completo.
  • Mango de actuación del anfitrión actorBody: div .xpl-actor > [data-host], independiente de fly() (x/y externo) y armEl. Ayudantes: salto (y-8 yoyo), inclinación (±4° hacia el objetivo señalado), sobresalto (retroceso+inclinación), giro de 360° en la mayor victoria. Reinicia cada corte. Personalidad de entrada de minipersonaje: asomarse desde detrás de un borde (desplazamiento x → 0) ANTES del pop.
  • Luz de recompensa: un #xplGlow radial difuminado compartido (mix-blend-mode:screen, tinte a través de variable CSS), posicionado + floreciente detrás del objeto héroe en el mayor ritmo de cada escena, reiniciado por corte. Sensación 'iluminada' instantánea por ~15 líneas.
  • Deriva de hora del día: siembra un filter base en #envFar al inicio (para que las interpolaciones interpolen, nunca salten desde none), luego ease brightness/hue-rotate según un cronograma de escena. Cambio de luz crepuscular a luz de noche en ~6s de tiempo de pantalla = atmósfera gratuita.
  • Desenfoque de capa de entorno: #envMid filter:blur(2px), #envFar filter:blur(4px) + escala .98 de paralaje de movimiento de cámara (.envLayer desplazamiento x suave de #xplCam). Parpadeo de capa de profundidad por ~12 líneas.
  • Granulado de cámara #xplGrain: SVG de ruido mezcla multiplicación (opacidad .15, apuntando a 8–12%) sobrepuesto en todo el escenario. No es un div: una imagen SVG base64 de un solo fotograma incrustada en el HTML (sin red, sin parpadeo de animación CSS), retinizada. Reemplaza con mix-blend-mode:overlay y opacidad .05 para una reproducción HDR más limpia.

Producción de VO (pipeline de ElevenLabs)

  • Construye el script VO: fusión de la transcripción sr-only con marcas de tiempo [MM:SS.mmm] de los límites de SCENES. Una línea = una oración, no diez segundos; las oraciones demasiado largas jadean. Marca los momentos de énfasis con *asteriscos*; ElevenLabs respeta la puntuación durante la generación.
  • Genera el archivo de voz: usa la CLI de ElevenLabs (el voice generate ...) en el guion con una voz consistente. Salida: assets/vo/topic-{chunk}.mp3.
  • Monta la vista previa name-vo.html: clona la construcción visual, inyecta pistas de audio (un <audio> por escena con data-start/data-end), maneja el reinicio de búsqueda/reproducción. Marca la línea de tiempo maestra para que coincida con la lectura (extiende SCENES[i] como se describe en el Contrato de arquitectura).
  • Distorsión de tiempo: limitador de velocidad, no restricción: la tarifa promedio de lectura de ElevenLabs es ~150 lpm (2.5 palabras/segundo). Una escena de 4s obtiene un máximo de ~10 palabras (o una toma de ritmo de lectura). Si el guion tiene 35 palabras y el diseño solo 8s, la escena se siente apresurada: extiende + corta en lugar de exprimir más rápido. El diseño de escena visual, no el llenado de palabras, es la restricción. Las escenas de ritmo de lectura duras (el logotipo de la empresa debe estar en pantalla durante 5 marcas de tiempo de habla) fuerza un SCENES[i] de ~10s, punto.

QA: el proceso de fotograma congelado

No te saltes esto. Cada error visual que detectas aquí ahorra una ronda de '¿puedes arreglar X?'. La reproducción a ciegas da una falsa confianza: el cerebro rellena las transiciones que GSAP no está reproduciendo realmente.

  1. Fotograma congelado de entrada: detente en t=0s de cualquier escena (haz clic en el borde izquierdo de la barra de progreso). runScene ejecuta gsap.set(); verifica que todos los elementos estén en su estado de reposo (opacidad 0, compensados, invisibles). Cualquier cosa que se vea lista para funcionar es una falla de reinicio.
  2. Fotograma congelado de salida: detente en t=duration-0.01s (justo antes del corte). El último tiempo de cada escena es su composición de 'revelación completa'; verifica que nada esté desalineado, superpuesto o descolorido. Luego verifica el mismo instante después de done() (clic en el borde derecho): la escena debe estar oculta a opacidad 0 hasta que showScene la muestre de nuevo.
  3. Verificación posicional: tres escenas aleatorias, fotograma congelado en el 50%. ¿Está el anfitrión APUNTANDO al lugar correcto (punta del lápiz en el objetivo)? ¿Los objetos en fila están TOCANDO el fondo? ¿Los objetos que caen se detuvieron SIN sobrepasar? Cualquier error de alineación indica una mala selección de parámetros (especialmente compensaciones de transformOrigin).
  4. Verificación de capas: ¿Está el anfitrión detrás del recipiente pero delante del fondo? z-index en el esqueleto: personajes 1, props 2, actor 3, recipientes 4, #xplGlow 5, texto 6, superposiciones 7. La violación solo ocurre con elementos adjuntos dinámicamente sin un índice establecido.
  5. Verificación de obstrucción: ¿Algún texto CSS .fu/.pp/.fi se superpone con un elemento g-hero animado? Son propietarios separados: la superposición se vuelve invisible en la pausa porque las pausas CSS congelan la animación mientras que GSAP todavía la tiene a opacidad 1.

Modo de movimiento reducido

El esqueleto ya maneja @media (prefers-reduced-motion:reduce): desactiva todo el escalonamiento de .fu/.pp/.fi, elimina animation-delay y establece la duración de todas las propiedades de transición/interpolación a 0. GSAP corrige a duration:0.001 (mínimo) e immediateRender:true. Verifica que el CTA aún funcione y que los mini-personajes no aparezcan parpadeando en reposo.

Notas y restricciones de la herramienta

  • Sin dependencias externas: el archivo final no debe tener etiquetas <script src=...> (GSAP está incluido). Sin imágenes externas (los SVG van en línea, los datos de imagen en base64 o se generan mediante JS). Sin llamadas a API. Sin CORS. Se sirve desde file:// en la fase de desarrollo y desde cualquier CDN/carpeta estática en producción.
  • Modo estricto: inicia con "use strict". Todos los contadores/índices de bucle se declaran con let. Sin temporizadores globales sin limpiar en el cambio de escena. Sin literales de objeto colgando sin const.
  • Sin Math.random para posiciones coreografiadas: como se describe en Physics2D burst — todas las posiciones de partículas/población están sembradas por un índice para que la reproducción sea idéntica. El estado de reposo del mini-personaje puede usar CSS animation-delay aleatorio si lo necesita.
  • El anfitrión no es un elemento de reproducción automática: no se reproduce al inicio a menos que window.xplAuto o la intersección del viewport lo active. Controlado por document.visibilityState en el cambio de pestaña.
  • Sin preferencia de tamaño de paso global: cada escena declara sus propias duraciones en SCENES. Sin aceleración/desaceleración de velocidad de reproducción (ese es un modismo de vista previa, no de entrega).
  • Los fotogramas congelados deben funcionar correctamente: sceneAt(frac) llama a runScene(i,frac) que reconstruye la línea de tiempo desde el índice 0, la avanza a la fracción y pausa. Las líneas de tiempo se reconstruyen, no se reutilizan, para que el estado de reinicio sea idéntico.
  • La transcripción sr-only debe coincidir con la longitud de SCENES: cada elemento en sr-only es una escena; su texto se muestra como descripción del capítulo en el cromo de búsqueda. El último elemento (SCENES.length-1) es el título de CTA.
  • CH_STARTS define las marcas del capítulo: array de índices de escena donde debe dibujarse un tick de capítulo. El último tick siempre está en SCENES.length-1 (CTA). Las marcas aparecen como ticks blancos delgados en la barra de progreso.

Resolución de problemas

  • La escena no se muestra: comprueba ACTS[i] — ¿comienza con gsap.set()? ¿Está el elemento envuelto en g-hero? ¿Coincide la ruta del selector en ACTS[i]? ¿Se llama a ACTS[i] en runScene(i)? ¿Se inicializa SPL{} antes de que se ejecute cualquier escena?
  • La animación se salta/corta: comprueba SCENES[i] — ¿es la duración menor que la suma de las duraciones de las interpolaciones? ¿Tiene la última interpolación duration establecida o usa el valor predeterminado de GSAP de .5s? Una escena de 2s con 4 interpolaciones de 1s se corta abruptamente.
  • DrawSVG no se dibuja: comprueba que el elemento SVG tenga stroke, stroke-width y fill="none". DrawSVG necesita una ruta SVG que comience desde un origen (0,0) y sea contigua — las rutas con agujeros (múltiples subrutas M) se dibujan secuencialmente pero parece que 'saltan'.
  • MorphSVG no se morph: comprueba que ambas rutas tengan el mismo número de puntos/comandos. DrawSVG y morphSVG no se mezclan en el mismo elemento.
  • El recorte de SplitText no funciona: comprueba que el elemento esté visible cuando se divide (no display:none, no opacidad 0 absoluta). SplitText necesita que el elemento tenga un layout para medir los intervalos de los caracteres. Divide UNA VEZ y oculta mediante opacidad.
  • El host no vuela: comprueba FL[i] — ¿tiene al menos 2 puntos de ruta? ¿El primer punto es la posposición del host (para que el host vuele desde allí)? ¿Tiene fly() una ruta motionPath válida para construir? ¿El anfitrión está renderizado por el DOM (no display:none)?

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills relacionados