Communitygithub.com

billel-chami/video-to-gsap

Convierte grabaciones de video, GIFs o prototipos de animación (como los de Figma) en animaciones GSAP optimizadas para Next.js 16, con extracción de tiempos, curvas de easing y trayectorias espaciales.

¿Qué es video-to-gsap?

Esta habilidad (_skill_) permite a un agente de IA analizar un video, GIF o prototipo de animación (por ejemplo, de Figma) y descomponer su coreografía de movimiento en parámetros precisos: duraciones, curvas de easing, trayectorias espaciales y solapamientos (stagger). Luego, implementa esas animaciones en Next.js 16 usando GSAP y el paquete oficial `@gsap/react` con el hook `useGSAP`, garantizando animaciones aceleradas por hardware (GPU) y sin fugas de memoria. Es ideal para diseñadores y desarrolladores que buscan trasladar microinteracciones fluidas de prototipos visuales a código de producción con 60/120 FPS, respetando las mejores prácticas de rendimiento (animar solo propiedades compuestas como `transform` y `opacity`) y la accesibilidad (`prefers-reduced-motion`). La habilidad se activa automáticamente cuando el usuario proporciona un clip de video, un GIF o un prototipo de Figma, o cuando se requiere animar elementos como carritos de compra, transiciones de página, expansiones de acordeón o tarjetas de producto.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/billel-chami/nextjs-medusa-handbook/tree/HEAD/.agents/skills/video-to-gsap

Preguntar en tu IA favorita

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

Documentación

Extracción de Movimiento desde Video y Prototipos (video-to-gsap)

1. Propósito y Disparadores

Las microinteracciones fluidas y el movimiento cinematográfico diferencian las experiencias de comercio de alta gama. Sin embargo, las animaciones web mal implementadas provocan bloqueos del hilo principal, fotogramas caídos (jank), fugas de memoria y una mala Interaction to Next Paint (INP). Esta habilidad gobierna la extracción e implementación de animaciones sedosas a 60/120 FPS.

Disparadores:

  • Cuando el usuario proporciona un clip de video, un GIF o un prototipo de movimiento de Figma.
  • Al animar deslizamientos de carrito, transiciones de página, expansiones de acordeón, hovers en tarjetas de producto o celebraciones de finalización de pago.
  • Al crear animaciones controladas por desplazamiento (scroll) con ScrollTrigger.

2. Protocolo de Descomposición de Movimiento

Al analizar un clip de movimiento, identifica sistemáticamente:

  1. La Secuencia de Coreografía:
    • Escenario / Disparador: ¿Qué acción inicia el movimiento (hover, scroll, cambio de ruta, clic)?
    • Anticipación: ¿Hay un sutil contra-movimiento antes del movimiento principal?
    • Acción y Recorrido: ¿Qué elementos se mueven, en qué direcciones y sobre qué distancia (px, rem o %)?
    • Asentamiento y Seguimiento: ¿Sobrepasa (spring/elastic) o desacelera suavemente (power3.out, expo.out)?
  2. Desglose de Tiempos:
    • Duración de cada elemento (ej., entrada del cajón: 450ms, desvanecimiento del fondo: 300ms).
    • Desfase (stagger) entre hijos escalonados (ej., tarjetas de cuadrícula de productos: 0.06s de desfase).
  3. Firma del Easing:
    • Lineal: estrictamente para bucles continuos (ej., marquee).
    • Ease-out (power2.out, expo.out): para entradas de UI (entrada rápida, asentamiento suave).
    • Ease-in (power2.in): para salidas de UI (acelera al desaparecer de la pantalla).
    • Ease-in-out (power3.inOut): para transformaciones de estado que permanecen visibles.

3. Estándares de Rendimiento y Aceleración por Hardware

Regla 1: Animar Solo Propiedades Compuestas

  • Permitido: transform (x, y, xPercent, yPercent, scale, rotation, skew) y opacity (o autoAlpha de GSAP).
  • Estrictamente Prohibido: Animar propiedades de layout o pintura (width, height, top, left, right, bottom, margin, padding, border-width). Estas fuerzan al CPU del navegador a recalcular la geometría del layout y repintar píxeles en cada fotograma, provocando degradación del INP y caída de fotogramas.

Regla 2: Cero Fugas de Memoria con useGSAP con Alcance

  • Usa siempre el paquete oficial @gsap/react y el hook useGSAP.
  • Proporciona una referencia scope al contenedor. Cada selector dentro del mismo tendrá alcance automático, y todas las líneas de tiempo, tweens e instancias de ScrollTrigger se revertirán y eliminarán limpiamente al desmontar el componente.
  • Esto evita oyentes de eventos zombis y retención de memoria en aplicaciones de una sola página (SPA) y en ciclos de recarga rápida de React 19.

Regla 3: Eliminar FOUC (Flashes de Contenido Sin Estilo)

  • Usa autoAlpha en lugar de opacity. autoAlpha establece visibility: hidden cuando la opacidad llega a 0, evitando clics fantasma y destellos de renderizado antes de la hidratación.
  • Alternativamente, declara estados ocultos por defecto en CSS y revélalos con gsap.fromTo.

4. Plan de Implementación en Producción

"use client";

import { useRef } from "react";
import gsap from "gsap";
import { useGSAP } from "@gsap/react";
import { ScrollTrigger } from "gsap/ScrollTrigger";

// Asegura que los plugins se registren de forma segura
if (typeof window !== "undefined") {
  gsap.registerPlugin(useGSAP, ScrollTrigger);
}

interface ProductShowcaseProps {
  readonly items: Array<{ id: string; title: string; price: string }>;
}

export function ProductShowcase({ items }: ProductShowcaseProps) {
  const containerRef = useRef<HTMLDivElement | null>(null);

  useGSAP(
    () => {
      // Línea de tiempo de entrada acelerada por hardware
      const tl = gsap.timeline({
        defaults: {
          ease: "expo.out",
          duration: 0.8,
        },
      });

      tl.from(".showcase-header", {
        autoAlpha: 0,
        y: 30,
        clearProps: "all", // Limpia estilos en línea después de la animación
      }).from(
        ".product-card",
        {
          autoAlpha: 0,
          y: 40,
          scale: 0.96,
          stagger: 0.08,
          duration: 0.7,
          clearProps: "transform,opacity",
        },
        "-=0.4" // Solapamiento sin fisuras
      );
    },
    { scope: containerRef } // Límite de limpieza con alcance
  );

  return (
    <section ref={containerRef} className="w-full py-16 px-6">
      <div className="showcase-header max-w-4xl mx-auto text-center mb-12">
        <h2 className="text-h1 font-bold text-content-primary">Colección Destacada</h2>
      </div>

      <div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-7xl mx-auto">
        {items.map((item) => (
          <article
            key={item.id}
            className="product-card will-change-transform bg-surface-elevated rounded-lg p-6 border border-border-subtle"
          >
            <h3 className="text-h3 font-semibold text-content-primary">{item.title}</h3>
            <p className="text-content-secondary mt-2">{item.price}</p>
          </article>
        ))}
      </div>
    </section>
  );
}

5. Cumplimiento de Movimiento Reducido

Respeta siempre a los usuarios que prefieren movimiento reducido:

const { contextSafe } = useGSAP({ scope: containerRef });

// Verifica la preferencia de accesibilidad
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

if (prefersReducedMotion) {
  // Renderiza instantáneamente en estado final de reposo sin animación
  gsap.set([".showcase-header", ".product-card"], { autoAlpha: 1, y: 0, scale: 1 });
  return;
}

Skills relacionados