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
- 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ónsr-only. - Copia
scaffold.htmla<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. Ejecutainline-gsap.pyen él y ábrelo antes de tocar nada; debe reproducirse. - 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_STARTSjuntos: son estructuras paralelas indexadas por escena. - 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 (arraySCENES, segundos por escena; última entrada999= retención de CTA;advance()llama adone()en él). - El texto/chips/leyendas entran a través de primitivas CSS (
.fufade-up,.pppop,.fifade-in) conanimation-delayen línea: baratos y reproducibles. La coreografía del héroe es GSAP:runScene(i)(llamado desdeshowScene) elimina la línea de tiempo anterior y construyegsap.timeline()a partir deFL[i](vuelo del anfitrión) +ACTS[i](acto de la escena). - Cada
ACTS[i]DEBE comenzar con reiniciosgsap.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 acurTl.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.htmlconstruida por el pipeline de ElevenLabs (ver Producción de VO). La transcripciónsr-onlyES el guion de VO. Reajustar el tiempo a una lectura = EXTENDERSCENES[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 (enfly()). 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. (layMarblesempaqueta 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 (
xyoyo), falla, se asienta; el segmento de superposición aparece conback.outy brilla (boxShadowyoyo 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 (
transformOriginen el pico), los contenidos vuelan uno por uno en arcosmotionPath({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 (backgroundColoryoyo). - Tentación luego destrucción: la respuesta brilla/pulsa (
scaleyoyo ×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 sobrescribestroke-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é enSPL{}: 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}conback.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\upara 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'}), luegorotation:'+=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])enfly()). - Caída CustomBounce con compresión:
CustomBounce.create('thud',{strength:.58,squash:2.4})crea facilidades emparejadas'thud'+'thud-squash'. El helperdrop(tl,targets,time,dur,stagger)ejecuta 3 interpolaciones sincronizadas: pop de opacidad,ycon 'thud',scaleX:1.45,scaleY:.55con 'thud-squash' (transformOrigin:'50% 100%'en el reinicio). Estrictamente mejor quebounce.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.pfxobsoleto 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 →
morphSVGa la silueta de flecha mientrasfillse interpola ('mismos objetos, nueva forma', literalmente). El reinicio necesitagsap.set(path,{morphSVG:ORIGINAL_D}): una ruta morph guarda sudmutado. - 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 bajotl.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-shadowen 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 spaneleva 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(...)porlinear-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
::beforeposicionada (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:visibleen 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#xplStageque 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 enrunScenecada corte. Nunca escales#xplStageen sí mismo: eso es defitScale. 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 defly()(x/y externo) yarmEl. 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
#xplGlowradial 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
filterbase en#envFaral inicio (para que las interpolaciones interpolen, nunca salten desdenone), 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:
#envMidfilter:blur(2px),#envFarfilter:blur(4px)+ escala.98de paralaje de movimiento de cámara (.envLayerdesplazamientoxsuave 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 conmix-blend-mode:overlayy 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-onlycon marcas de tiempo[MM:SS.mmm]de los límites deSCENES. 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 condata-start/data-end), maneja el reinicio de búsqueda/reproducción. Marca la línea de tiempo maestra para que coincida con la lectura (extiendeSCENES[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.
- Fotograma congelado de entrada: detente en t=0s de cualquier escena (haz clic en el borde izquierdo de la barra de progreso).
runSceneejecutagsap.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. - 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 queshowScenela muestre de nuevo. - 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). - Verificación de capas: ¿Está el anfitrión detrás del recipiente pero delante del fondo?
z-indexen el esqueleto: personajes 1, props 2, actor 3, recipientes 4,#xplGlow5, texto 6, superposiciones 7. La violación solo ocurre con elementos adjuntos dinámicamente sin un índice establecido. - Verificación de obstrucción: ¿Algún texto CSS
.fu/.pp/.fise superpone con un elementog-heroanimado? 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 desdefile://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 conlet. Sin temporizadores globales sin limpiar en el cambio de escena. Sin literales de objeto colgando sinconst. - 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 CSSanimation-delayaleatorio si lo necesita. - El anfitrión no es un elemento de reproducción automática: no se reproduce al inicio a menos que
window.xplAutoo la intersección del viewport lo active. Controlado pordocument.visibilityStateen 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 arunScene(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-onlydebe coincidir con la longitud deSCENES: cada elemento ensr-onlyes 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_STARTSdefine las marcas del capítulo: array de índices de escena donde debe dibujarse un tick de capítulo. El último tick siempre está enSCENES.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 congsap.set()? ¿Está el elemento envuelto eng-hero? ¿Coincide la ruta del selector enACTS[i]? ¿Se llama aACTS[i]enrunScene(i)? ¿Se inicializaSPL{}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óndurationestablecida 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-widthyfill="none". DrawSVG necesita una ruta SVG que comience desde un origen (0,0) y sea contigua — las rutas con agujeros (múltiples subrutasM) 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í)? ¿Tienefly()una rutamotionPathválida para construir? ¿El anfitrión está renderizado por el DOM (nodisplay:none)?