Diseño de movimiento (versión HyperFrames)
Los documentos de HyperFrames te enseñan la API; este archivo se encarga del gusto. Los números provienen de un proyecto real que ya ha sido publicado. Tómalos como valores predeterminados: puedes desviarte, pero debe ser intencional, no porque no te hayas fijado.
Adaptado del skill
motion-designde whaleyxbt/claude-motion (MIT, verLICENSEen la misma carpeta). La versión original estaba enfocada en Remotion; esta versión está reescrita para HyperFrames (HTML + GSAP) e incluye reglas de composición tipográfica para chino tradicional. Los párrafos marcados con «(nuevo en esta versión)» no forman parte del contenido original.
División del trabajo con los skills oficiales de HyperFrames (nuevo en esta versión)
Este equipo también tiene instalados los skills oficiales de HyperFrames de HeyGen (hyperframes, hyperframes-core, hyperframes-animation). La división del trabajo es la siguiente:
- Los skills oficiales se encargan del «cómo hacerlo»: estructura del proyecto, atributos
data-*, escritura de API, enrutamiento de flujos, componentes ready-made del registry. En caso de conflicto con la escritura de la API, prevalece la oficial. - Este archivo se encarga del «gusto»: easing, ritmo, tiempos de permanencia, tipografía, paleta de colores, composición tipográfica china. Al usar las reglas / blueprints del
hyperframes-animationoficial, los números de tiempo y easing siguen teniendo como predeterminado lo establecido en este archivo. - Revisión: siempre a través de
review-loop, que ya incluye lahyperframes checkoficial.
0. Reglas estrictas de HyperFrames (nuevo en esta versión)
Si se infringen, la imagen parpadeará, se desplazará o dará resultados diferentes cada vez que se renderice:
-
El tiempo lo determina HTML: cada escena es un elemento con
class="clip", que llevadata-startydata-durationen la línea de tiempo. El elemento raíz debe tenerdata-composition-idy undata-durationexplícito. -
Las animaciones las gestiona GSAP:
gsap.timeline({ paused: true }), registrado enwindow.__timelines["<composition-id>"], cuya clave debe ser igual adata-composition-id. -
Cada tween importante debe tener una posición explícita (tercer parámetro); cuando ambos extremos son importantes, usa
fromTo(), porque al renderizar se buscará saltando. -
Solo mueve
transformyopacity; no muevas repetidamentetop/left/width/height. -
Prohibido:
transition/@keyframesde CSS,Date.now(),requestAnimationFrame,setTimeout,Math.random()sin semilla, recursos que se fetch durante la renderización. -
No uses scripts para reproducir, pausar o buscar en audio/video, ni uses scripts para mostrar u ocultar clips según el tiempo. Todo esto se delega a los atributos
data-*. Para mover un video, mueve el elemento contenedor externo. -
La aleatoriedad siempre debe usar una función con semilla:
function rand(seed) { let t = (seed += 0x6D2B79F5); t = Math.imul(t ^ (t >>> 15), t | 1); t ^= t + Math.imul(t ^ (t >>> 7), t | 61); return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }
1. El tiempo se concentra en un solo lugar
-
Cada beat es un punto de tiempo con nombre (en segundos), agrupado por escena (
s1,s2…), escrito entimeline.jsen la raíz del proyecto:window.TL = { s1: { start: 0, title: 0.3, items: [1.2, 1.45, 1.7], exit: 3.6 }, s2: { start: 3.4, drawOn: 3.5, hook: 5.2, end: 8 }, };En
index.html, antes de todos los scripts de composición, carga primero<script src="timeline.js"></script>. -
Los parámetros de posición de GSAP siempre se toman de
TL(se permite escritura relativa comoTL.s1.title,TL.s1.exit + 0.05); no escribas segundos fijos dentro de las escenas. -
Los
data-start/data-durationdel contenedor de la escena deben coincidir con los límites de la escena enTL. Al re-temporizar, primero modificatimeline.js, luego sincroniza estos dos atributos. -
El sonido y la narración se colocan con
<audio data-start="…">en los mismos beats. Los tiempos de captura de pantalla del review-loop también se toman deTL, por lo que la imagen, el sonido y la revisión se mueven juntos. -
Todas las imágenes solo pueden ser determinadas por el tiempo; ver sección 0.
2. Easing
Las cuatro curvas del original se reconstruyen con precisión en GSAP usando CustomEase. Carga gsap@3/dist/CustomEase.min.js y luego registra con gsap.registerPlugin(CustomEase):
CustomEase.create("enter", "0.16,1,0.3,1"); // easeOut
CustomEase.create("exit", "0.6,0,0.9,0.35"); // easeIn
CustomEase.create("move", "0.65,0,0.35,1"); // easeInOut
CustomEase.create("land", "0.55,0,0.2,1.12"); // overshoot
| Curva | Uso | Nombre integrado más cercano |
|---|---|---|
enter = bezier(0.16, 1, 0.3, 1) | Entrada, revelación, cualquier «llegada» | expo.out (casi idéntico) |
exit = bezier(0.6, 0, 0.9, 0.35) | Salida: rápida, sin titubeos | Aproximadamente power3.in |
move = bezier(0.65, 0, 0.35, 1) | Movimiento entre dos estados (volteo, anclaje, transformación) | power2.inOut (exactamente igual) |
land = bezier(0.55, 0, 0.2, 1.12) | Valores que «se asientan» (control deslizante que llega a una marca) | No hay un buen sustituto integrado; usa CustomEase |
ease: "none" (lineal) solo se usa en movimiento continuo: rotación, deriva, partículas, segundero.
Para que una animación siga a otro valor (por ejemplo, subtítulos que siguen la posición de un control deslizante), usa el mismo tween para impulsar un objeto proxy y deriva en onUpdate; no le des otro reloj independiente.
3. Elasticidad
El original usaba resortes físicos de Remotion; GSAP no tiene física de resortes. La siguiente tabla son los valores aproximados elegidos en esta versión (nuevo en esta versión, no son números originales). Después de la salida, usa el review-loop para confirmar la sensación:
| Sensación | Configuración GSAP | Uso |
|---|---|---|
| Asentamiento predeterminado | back.out(1.2), 0.6 s | Entrada de UI general |
| Pesado, sólido | power3.out, 0.8–1.0 s | Paneles grandes, reversiones |
| Muesca de perilla | back.out(1.7), 0.35 s | El control salta a una muesca |
| Rebote | back.out(2.2), 0.45 s | Anotaciones, insignias, puntos de éxito |
| Acento elástico | elastic.out(1, 0.4), 0.9 s | Momento culminante, una sola vez por video |
Usa elasticidad para cosas con sensación física (UI, objetos); usa curvas bezier para texto y movimientos con sensación de cámara.
4. Ritmo
- Stagger: Palabras en inglés aproximadamente 0.09 s; caracteres chinos uno por uno aproximadamente 0.04–0.05 s, por palabra aproximadamente 0.09 s (parte china nueva en esta versión); ítems de lista y etiquetas aproximadamente 0.2–0.25 s; anillos y puntos aproximadamente 0.06 s.
- Revelación de texto aproximadamente 0.8 s, usando máscara: exterior
overflow: hidden, interioryPercent: 100 → 0más un poco de rotación (rotation: 3 → 0). - La salida es aproximadamente la mitad de la entrada (0.35–0.55 s contra 0.7–1.25 s), la salida usa la curva
exit. - Las escenas deben solaparse: la siguiente escena comienza a dibujarse antes de que la anterior haya desaparecido por completo (por ejemplo,
s2.drawOn4.02 s antes ques1.flipEnd4.4 s). Un corte abrupto a blanco parece «cargando». - Escritura aproximadamente 0.035 s por carácter, el cursor parpadea a aproximadamente 2.4 Hz cuando está inactivo (usa
stepsosetprogramados en la línea de tiempo, no temporizadores). - Pausa de lectura: cada estado que deba leerse debe detenerse después de asentarse. Frases cortas al menos 1 s, más de tres palabras añade aproximadamente 0.25 s por palabra extra; en chino, aproximadamente 0.25 s por cada 4 caracteres extra (nuevo en esta versión). La última frase final al menos 2 s. La versión de 22 segundos del original existe porque la versión de 15 segundos tenía texto que parpadeaba demasiado rápido: cuando no estés seguro, detente más tiempo y mueve menos.
5. Tipografía
- Máximo tres familias: Serifa para exhibición, Sans-serif para interfaz, Monoespaciada (para etiquetas, prompts, números).
- Inglés (original): Instrument Serif / Inter / JetBrains Mono.
- Chino tradicional (nuevo en esta versión): Noto Serif TC / Noto Sans TC, números y etiquetas con JetBrains Mono. Los archivos de fuentes se colocan en
assets/fonts/del proyecto, se cargan con@font-face, no dependas de las fuentes del sistema (cambiarían de computadora).
- El texto de exhibición en inglés debe ser grande (aproximadamente 138 px en un lienzo de 1080 de ancho), espaciado de letras ajustado (
-0.02em),line-height: 1. - Texto de exhibición en chino (nuevo en esta versión): aproximadamente 96–120 px en 1080 de ancho, no más de aproximadamente 12 caracteres por línea, espaciado de letras
0a0.02em(en chino no uses espaciado negativo),line-height: 1.15–1.25. - Un punto focal por línea: en inglés usa una palabra en cursiva con color de énfasis; en chino no hay cursiva real, usa color de énfasis más peso para llevar el punto focal (nuevo en esta versión).
- Etiquetas monoespaciadas: mayúsculas,
letter-spacing: 0.2–0.24em, color atenuado. Son solo decoración; si el público debe leer algo, hazlo grande. - Prueba en móvil: a 360 px de ancho (el tamaño real que se ve en las redes sociales), la información clave aún debe ser legible. Verifica con la hoja de contactos.
6. Paleta de colores
- (Nuevo en esta versión) Toda la pieza se define con tres colores principales, como una plantilla de presentación, decididos por el usuario: color de fondo
bg, color principalfg(texto y línea), color de énfasisaccent, escritos entheme.jsondel proyecto, aplicados con el scripttheme.pydel skillmotion-explainer(o la versión mejorada con imágenesmotion-explainer-images). El color de énfasis solo se usa para «respuesta, conclusión, números clave, tarjetas de capítulo». - La paleta de colores se define como variables CSS en
:root(--bg,--ink,--muted,--accent…); no aparezcan nuevos códigos de color en las escenas. - Solo hay un color de énfasis, y tiene significado: lo que cambia, la respuesta, el ganador. Si todo es color de énfasis, entonces nada lo es.
- Los halos están impulsados por el estado, no por el tiempo (
glow = effort): la luz debe contar la historia.
7. Textura: nada está completamente quieto
- Granulado de película: superposición de filtro SVG
feTurbulence, opacidad aproximadamente 0.09, cambiaseedcada dos fotogramas (programado conseten la línea de tiempo, la semilla se calcula a partir del número de fotograma). - Viñeta + cuadrícula de puntos, que se desplaza unos pocos px por segundo: viñeta con
radial-gradient, la cuadrícula con un tween lineal que abarca toda la pieza. - «Vibración de línea» dibujada a mano (
feTurbulence+feDisplacementMap, también cambia semilla cada dos fotogramas): se usa en estados de boceto, baja finalización; se desvanece cuando la calidad mejora. - Los elementos inactivos deben respirar: un reloj que avanza, un cursor que parpadea, una rotación lenta.
8. Coherencia y transiciones
- Más vale que los objetos continúen a hacer un corte brusco. La barra de prompts, las chispas y el control deslizante del original atraviesan escenas y cambian de rol; esa es la diferencia entre «diseñado» y «improvisado». En HyperFrames, los objetos que cruzan escenas se colocan en la composición raíz, no dentro de una escena.
- Cada transición debe ser generada por un objeto en la pantalla (cinco puntos de resultado se fusionan en uno, que luego se convierte en un anillo de luz). No uses transiciones de cortinilla estándar.
- Usa la velocidad: los rastros de movimiento y las compresiones se derivan de «la diferencia de valor entre este fotograma y el anterior»; no los simules artificialmente.
- Cada video tiene un momento culminante (anillo de luz + impacto). Ve construyendo hacia él; no lo uses demasiado pronto.
9. Antipatrones
- Todo se desvanece al mismo tiempo, o todo usa la misma duración.
- Usar easing lineal para cosas que arrancan y se detienen.
- Texto que aún se está moviendo cuando debería estar siendo leído.
- Más de un punto focal en un solo fotograma.
- Contenido a menos de aproximadamente 60 px del borde de la pantalla (zona de seguridad), a menos que sea un recorte intencional.
- El primer fotograma está en blanco o negro: cuando se reproduce automáticamente sin audio en redes sociales, el primer fotograma es la miniatura.
- (Nuevo en esta versión) Controlar la reproducción de audio/video o la visualización de clips con scripts, usar animaciones CSS, usar aleatoriedad sin semilla; ver sección 0.
Flujo de trabajo
- Primero escribe los beats en
timeline.js(storyboard con números), confirma el ritmo con el usuario antes de empezar. - Usa
hyperframes_initde kinocut para crear el proyecto; cada escena es una composición encompositions/, los componentes compartidos y los objetos que cruzan escenas se colocan enindex.html. - Después de cada modificación significativa, ejecuta el skill
review-loop. - Después de bloquear el tiempo visual, procesa el sonido: efectos de sonido y música de fondo con
<audio data-start>sincronizados con los beats deTL. El acento y la emoción de la narración en chino se dejan al oído del usuario; no los sustituyas con puntuaciones ASR o de similitud (nuevo en esta versión).